题目链接 找不到
分析
这道题的解法感觉还是很多的,写完后看了看题解,发现这道题模拟可能是最low的算法了,什么贪心啊,BFS啊,都能解决这个问题,然而我就用的模拟,模拟大法好,不会别的,首先直接模拟的话复杂度最差大约(O(250,000,000,000)),显然不是我们想要的,再仔细观察,因为这个门,一次只能出一个人,那么当人很多时,多次移动人之后一定会造成一个现象————人挤成一堆了,这时就可以保证一个步数就能让一个人出去,所以需要步数就是当前还剩的人,大概多少步后会成为这个现象呢?不是很好找,但可以保证这个步数在1000步以内,因为横着数两块每块最多有500,竖着也最多500,所以当步数大于1000时直接跳出循环就行了,这么做的时间复杂度大概在(O(100000000))左右,时限3s,可以A掉。
#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;
}