IOI模拟真题试卷(含详细答案解析)_第1页
IOI模拟真题试卷(含详细答案解析)_第2页
IOI模拟真题试卷(含详细答案解析)_第3页
IOI模拟真题试卷(含详细答案解析)_第4页
IOI模拟真题试卷(含详细答案解析)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

IOI模拟真题试卷(含详细答案解析)考试说明1.本套试卷参照IOI正式赛事命题风格出题,共2道大题,满分200分,单题限时5小时,符合IOI单人独立解题赛制。2.题目涵盖贪心、模拟、基础思维优化,难度贴合IOI中档真题梯度,兼顾基础能力与算法思维考察。3.答题要求:程序读写标准输入输出,无特殊文件依赖,代码简洁高效,能够通过全部边界测试数据。4.评分规则:每组测试数据按点给分,部分正确解法可获得部分分数,完全通过所有数据得满分。题目一:时钟谜题(100分)题目背景现有9个时钟均匀排布为3×3矩阵,所有时钟初始时间均为12点、3点、6点、9点四种整点状态。我们仅有9种固定操作,每种操作可以同时拨动指定若干个时钟,每次拨动会将对应时钟顺时针转动90°(3小时)。操作规则9种操作对应的拨动时钟位置如下(矩阵位置记为(1,1)至(3,3)):操作1:拨动(1,1)、(1,2)、(2,1)操作2:拨动(1,1)、(1,2)、(1,3)操作3:拨动(1,2)、(1,3)、(2,3)操作4:拨动(1,1)、(2,1)、(3,1)操作5:拨动(2,1)、(2,2)、(2,3)操作6:拨动(1,3)、(3,1)、(3,3)操作7:拨动(3,1)、(3,2)、(2,1)操作8:拨动(3,1)、(3,2)、(3,3)操作9:拨动(2,3)、(3,2)、(3,3)题目要求给定9个时钟的初始状态,每个时钟用数字表示当前时间:0代表12点,1代表3点,2代表6点,3代表9点。每次操作最多执行3次(执行4次等同于不操作,可直接舍去)。请找出一组操作次数最少的操作方案,使得所有时钟最终归零(全部回到12点)。若存在多组最优解,输出操作序号字典序最小的方案。输入格式一行9个整数,依次对应3×3矩阵从第一行到第三行的9个时钟初始状态,数字范围0~3。输出格式一行若干个整数,为最优操作序列的操作序号,数字之间用空格分隔。无需输出操作次数。输入样例330222111输出样例123456789题目一详细答案解析1.解题核心思路本题核心是暴力枚举+状态校验,属于IOI经典状态模拟题。由于每种操作仅需枚举0~3次(4次操作无意义),且仅有9种操作,整体枚举总量可控,不会超时。关键点:前8种操作的次数全部枚举完成后,第9种操作的次数可以直接通过最后一个时钟的状态推导得出,无需额外枚举,大幅压缩时间复杂度。同时全程记录最优解,优先保留操作次数更少、字典序更小的方案。2.算法逻辑拆解第一步:预处理所有操作对应的时钟位置映射,建立固定对应关系,方便后续状态更新。第二步:四重循环枚举前8种操作的执行次数(0~3),每次枚举更新所有时钟的当前状态。第三步:根据最后一个时钟的剩余状态,计算第9种操作需要执行的次数(0~3),保证最后一个时钟归零。第四步:校验全部时钟是否归零,若满足条件则统计总操作次数,对比当前最优解,更新最优方案。第五步:枚举结束后,输出最终最优操作序列。3.复杂度分析时间复杂度:O(4空间复杂度:O(1),仅存储固定状态与操作序列,无额外空间开销。4.满分代码(C++)cpp

#include<iostream>

#include<vector>

#include<climits>

usingnamespacestd;

//预处理9个操作对应的时钟下标(0~8)

intop[10][10]={

{},

{0,1,3},//操作1

{0,1,2},//操作2

{1,2,5},//操作3

{0,3,6},//操作4

{3,4,5},//操作5

{2,6,8},//操作6

{3,6,7},//操作7

{6,7,8},//操作8

{5,7,8}//操作9

};

intcnt[10];

intbest=INT_MAX;

vector<int>ans;

//校验当前操作是否合法,并更新最优解

voidcheck(ints[]){

intt[9];

for(inti=0;i<9;i++)t[i]=s[i];

//执行1-8号操作

for(inti=1;i<=8;i++){

for(intj=0;j<3;j++){

t[op[i][j]]=(t[op[i][j]]+cnt[i])%4;

}

}

//推导9号操作次数

cnt[9]=(4-t[8])%4;

//执行9号操作

for(intj=0;j<3;j++){

t[op[9][j]]=(t[op[9][j]]+cnt[9])%4;

}

//判断是否全部归0

boolok=true;

for(inti=0;i<9;i++)if(t[i]!=0)ok=false;

if(!ok)return;

//统计总步数

intsum=0;

for(inti=1;i<=9;i++)sum+=cnt[i];

//更新最优解:步数更少或步数相同字典序更小

if(sum<best){

best=sum;

ans.clear();

for(inti=1;i<=9;i++){

for(intj=0;j<cnt[i];j++)ans.push_back(i);

}

}

}

intmain(){

ints[9];

for(inti=0;i<9;i++)cin>>s[i];

//枚举前8个操作的次数0-3

for(cnt[1]=0;cnt[1]<4;cnt[1]++)

for(cnt[2]=0;cnt[2]<4;cnt[2]++)

for(cnt[3]=0;cnt[3]<4;cnt[3]++)

for(cnt[4]=0;cnt[4]<4;cnt[4]++)

for(cnt[5]=0;cnt[5]<4;cnt[5]++)

for(cnt[6]=0;cnt[6]<4;cnt[6]++)

for(cnt[7]=0;cnt[7]<4;cnt[7]++)

for(cnt[8]=0;cnt[8]<4;cnt[8]++){

check(s);

}

//输出答案

for(intx:ans)cout<<x<<"";

return0;

}5.得分点说明1.正确预处理操作映射关系,得20分;2.完成前8种操作枚举逻辑,得30分;3.正确推导第9种操作次数,得20分;4.实现最优解筛选(最少步数+字典序最小),得20分;5.代码无边界bug、通过全部测试数据,得满分100分。题目二:公交车调度(100分)题目背景一条公交线路从早到晚依次发出多班公交车,所有公交车按照固定顺序发车,且发车时间严格递增。现有若干乘客,每位乘客会在某一时刻到达车站,只会乘坐到达时间之后发出的第一班公交车。为控制运营成本,调度部门可以取消部分班次公交车,但需要保证所有乘客都能乘车出行。同时规定,首班、末班公交车不得取消。题目要求给定所有公交车发车时间和所有乘客到站时间,求最多可以取消多少班公交车。输入格式第一行两个整数n,m,分别代表公交车班次数量、乘客数量(2≤n≤1000,0≤m≤10000)。第二行n个严格递增整数,代表n班公交车的发车时间。第三行m个整数,代表m位乘客的到站时间。输出格式输出一个整数,为最多可取消的公交车班次数量。输入样例531020304050152535输出样例2样例解释保留10、30、50三班车即可满足所有乘客需求:15分乘客坐30班车,25分乘客坐30班车,35分乘客坐50班车。最多取消2、4两班,共取消2班。题目二详细答案解析1.解题核心思路本题为经典贪心算法问题,核心逻辑是尽可能保留靠后的公交车,最大化可取消班次。解题关键:先对乘客时间排序,从后往前遍历公交车班次。对于每一班车,判断是否有乘客只能乘坐该班车(无更晚的可选班车),若有则必须保留,否则可以取消。首班、末班强制保留。2.算法逻辑拆解第一步:对所有乘客到站时间进行升序排序,方便二分查找匹配班车。第二步:强制标记首班、末班公交车为保留班次。第三步:从倒数第二个班车向前遍历至第二个班车:1.找到所有大于当前乘客时间的最小班车;2.若当前班车是部分乘客的唯一可选班车,则必须保留;3.其余情况全部取消。第四步:统计总班次与保留班次的差值,即为最多可取消班次。3.复杂度分析排序乘客时间复杂度O(mlog⁡m),遍历班车+二分匹配复杂度4.满分代码(C++)cpp

#include<iostream>

#include<vector>

#include<algorithm>

usingnamespacestd;

intmain(){

intn,m;

cin>>n>>m;

vector<int>bus(n);

for(inti=0;i<n;i++)cin>>bus[i];

vector<int>pas(m);

for(inti=0;i<m;i++)cin>>pas[i];

sort(pas.begin(),pas.end());

intkeep=2;//首尾必保留

//遍历中间所有班车

for(inti=1;i<n-1;i++){

//找到第一个大于当前班车时间的乘客

autoit=upper_bound(pas.begin(),pas.end(),bus[i-1]);

boolneed=false;

for(;it!=pas.end()&&*it<=bus[i];it++){

//该乘客只能坐当前班车,无更优后续班车

if(bus[i+1]>*it)need=true;

}

if(need)keep++;

}

cout<<n-keep<<endl;

return0;

}5.得分点说明1.完成乘客数据排序、首尾班次保留逻辑,得2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论