Emergency Evacuation 模拟了一下

题目链接 找不到


分析

这道题的解法感觉还是很多的,写完后看了看题解,发现这道题模拟可能是最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;
}
posted @ 2020-04-10 20:02  An_Fly  阅读(120)  评论(0编辑  收藏  举报