Problem C Emergency Evacuation 一道思维题
题目描述
输入
输出
样例
样例输入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
5 2 7 1 1 1 2 1 3 2 3 2 4 4 4 5 2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
500 500 16 1 1 1 2 1 999 1 1000 2 1 2 2 2 999 2 1000 3 1 3 2 3 999 3 1000 499 500 499 501 499 999 499 1000
样例输出
样例输出一
9
样例输出二
1008
一句话题意:给你一个车厢和一些人,这些人都坐在座位上,求这些人全部出去的时间最小值。
分析
我们先拿最简单的情况来说:车厢中只有一个人,比如下面这幅图
那么很显然,他到达出口所需要的花费步数为5+1=6
是不是太简单了,那我们再加一个人
那么新加的这个人到出口所需要的步数为2+2=4
因为6大于4,所以在第一个人到达距离出口的步数为2的地方时,第二个人已经从出口离开车厢,不会对结果造成影响
最终答案仍为6
那么我们再加一个人
第三个人到达出口所需要的时间为1+1=2
因为2、4、6都不相等,所以此时最终答案仍然为6
这时,我们要加一个最为关键的人——四号
我们会发现4号到达出口的时间和1号一样都为6
这时,问题就来了,1号和4号显然不能同时走出车厢,而他们走出车厢的最小步数又都为6
所以,1号和4号必定有一个人需要停留一步,在下一步时再排到另一个人的后面
这时,因为有了停留的这一步,最大步数就变成了6+1=7
我们再加一个人,把最后一种情况考虑到
5号到达门口需要的最少步数为2+5=7,那么他能不能在第七步时走出车厢呢
答案是不能的,因为前面的1号和4号都需要走六步才能到达出口
1号和4号中必定有一个人会花费7步,这时会与5号的7步相冲突
所以5号又要推迟一步,变成8步
同样的我们再加一个人
6号需要的步数也为7,所以5号又要推迟一步,变为9步
最后我们再把剩余的一个人加上
他的步数为5步,所以不会对结果产生影响
所以样例一的最终答案为9步
代码
知道了思路,下一步就是代码实现了
我们要先处理出每一个人到达出口的最小步数,然后排一下序
最后我们由大到小遍历,如果遇到相同的就把步数往后推一个
需要注意的是,数组要开500*500*2,不要开小了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 using namespace std; 6 const int maxn=5000011;//数组不要开小了 7 int r,s,p; 8 int jl[maxn]; 9 int solve(int bb){ 10 if(bb<=s) return s-bb+1; 11 else return bb-s; 12 } 13 int main(){ 14 scanf("%d%d%d",&r,&s,&p); 15 for(int i=1;i<=p;i++){ 16 int aa,bb; 17 scanf("%d%d",&aa,&bb); 18 jl[i]=r-aa+1+solve(bb);//求出每个节点到出口的最小步数 19 } 20 sort(jl+1,jl+1+p);//排序 21 int ans=-1,cnt=0; 22 for(int i=1;i<=p;i++){ 23 if(jl[i]==cnt || ans>=jl[i]) ans++; 24 //如果出现相同的或者是当前的最大步数大于等于该节点的步数,步数往后推移一步 25 //这里的当前的最大步数大于等于该节点的步数说明之前一定遍历到了比jl[i]更小的节点 26 //而且该节点被遍历了两次及以上,这时我们也需要把ans++ 27 else ans=max(ans,jl[i]);//不相同取较大值 28 cnt=jl[i];//记录上一个元素 29 } 30 printf("%d\n",ans); 31 return 0; 32 }