Codeforces 625E Frog Fights (Codeforces Round #342 (Div. 2) E) 题解

来源:互联网 发布:js模拟按键f11 编辑:程序博客网 时间:2024/06/06 00:27

题目来源:http://codeforces.com/problemset/problem/625/E


题意:有n只青蛙和一个有m个格子的环形桌面,格子从1到m编号,青蛙也从1到n编号,每只青蛙都有一个初始的格子和初始移动距离,从第一只青蛙开始移动,在移动路径上的青蛙将会被撞出游戏,每撞一只青蛙,移动距离减小1,然后下一只未被踢出游戏的青蛙开始移动,从1到n都移动或被踢出游戏后再循环一次,直到将不再有青蛙被踢出游戏时游戏结束,输出还在场上的青蛙的个数,并输出这些青蛙。


解题思路:我们可以先计算出桌面上相邻两只青蛙碰撞时前一只青蛙要走的步数,最先发生碰撞的一定是步数最少且编号最小的青蛙,踢出被撞的青蛙后,由于青蛙的移动距离减小,改变与移动的青蛙相邻的青蛙之间步数,再进行一次上述操作,知道不会有青蛙被撞为止。其实在这个过程中,青蛙相撞要走的步数都事先被计算好了,之后并不要模拟青蛙的移动。可以用pair<int,int>储存青蛙与下一只青蛙相撞要走的步数和青蛙的编号,把pair放入set中就会自动拍好序啦!


代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>#include<set>using namespace std;int n,m;int p[100000+10],a[100000+10];//p[]表示编号为i的青蛙的坐标,a[]表示编号为i的青蛙跳的距离int x[100000+10];//x[]表示排第i位的青蛙的编号int nextt[100000+10],pre[100000+10];bool cmp(int i,int j){return p[i]<p[j];}typedef pair<int,int>pii;set<pii>st;set<pii>::iterator it;const int inf=0x3f3f3f3f;int dis(int i,int j)//返回i青蛙到j青蛙要跳多少步,如果返回inf则不会撞到{if(i==j)return inf;int d=(p[j]-p[i]+m)%m;//d表示编号为i的青蛙到j的距离if(i>j) d=(d+a[j])%m;if(d<=a[i])return 1;if(a[i]<=a[j])return inf;int s=a[i]-a[j];return (d-a[j]-1)/s+1;//设要走x步相撞,由方程x*a[i]-(x-1)*a[j]=d得,x=(d-a[j])/s,但由于x不一定是整数,所以x=(d-a[j]-1)/s+1}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d%d",&p[i],&a[i]);p[i]--;x[i]=i;}sort(x+1,x+n+1,cmp);//使青蛙按坐标从小到大排列for(int i=1;i<=n;i++)//创建双链表模拟环形桌面上的青蛙{if(i<n) nextt[x[i]]=x[i+1];else nextt[x[i]]=x[1];pre[nextt[x[i]]] =x[i];}for(int i=1;i<=n;i++){st.insert(make_pair(dis(i,nextt[i]),i));}while(!st.empty()){it=st.begin();if(it->first==inf)break;int i=it->second;st.erase(it);st.erase(make_pair(dis(nextt[i],nextt[nextt[i]]),nextt[i]));st.erase(make_pair(dis(pre[i],i),pre[i]));p[i]+=dis(i,nextt[i]);//发生碰撞后青蛙的移动距离减小1,但前面的移动已经发生,会对相邻的两只青蛙的碰撞步数产生影响,所以要加上步数*1抵消影响a[i]--;nextt[i]=nextt[nextt[i]];//删除被撞的青蛙pre[nextt[i]]=i;st.insert(make_pair(dis(pre[i],i),pre[i]));//重新计算相邻青蛙的步数st.insert(make_pair(dis(i,nextt[i]),i));}printf("%d\n",st.size());for(it=st.begin();it!=st.end();it++){if(it!=st.begin())printf(" ");printf("%d",it ->second);}printf("\n");return 0;}

1 0
原创粉丝点击