这道题的解法感受仍是不少的,写完后看了看题解,发现这道题模拟多是最low的算法了,什么贪心啊,BFS啊,都能解决这个问题,然而我就用的模拟,模拟大法好,不会别的,首先直接模拟的话复杂度最差大约\(O(250,000,000,000)\),显然不是咱们想要的,再仔细观察,由于这个门,一次只能出一我的,那么当人不少时,屡次移动人以后必定会形成一个现象————人挤成一堆了,这时就能够保证一个步数就能让一我的出去,因此须要步数就是当前还剩的人,大概多少步后会成为这个现象呢?不是很好找,但能够保证这个步数在1000步之内,由于横着数两块每块最多有500,竖着也最多500,因此当步数大于1000时直接跳出循环就好了,这么作的时间复杂度大概在\(O(100000000)\)左右,时限3s,能够A掉。ios
#include<iostream> #include<algorithm> using namespace std; const int N=1e3+10; int pre[N][N]; int main(){ int r,s,p; cin>>r>>s>>p; for(int i=1;i<=p;i++){ int a,b; cin>>a>>b; if(b>s)b++; pre[a][b]=1; } int ans=0,k=s<<1|1; while(p){ ans++; if(pre[r][s+1])pre[r][s+1]=0,p--; for(int i=r;i;i--){ if(pre[i][s+1]&&pre[i+1][s+1]==0)swap(pre[i][s+1],pre[i+1][s+1]); for(int j=s;j;j--) if(pre[i][j]&&pre[i][j+1]==0)swap(pre[i][j],pre[i][j+1]); for(int j=s+2;j<=k;j++) if(pre[i][j]&&pre[i][j-1]==0)swap(pre[i][j],pre[i][j-1]); } if(ans>=N)break; } cout<<ans+p; }