Codeforces 1105D(Kilani and the Game,双队列bfs)

AC代码:

#include<bits/stdc++.h>
#define ll long long
#define endl '
'
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
struct node{
    int x,y,t;
    node(int xx,int yy,int tt){
        x=xx;y=yy;t=tt;
    }
};
int s[15],vis[1005][1005];char a[1005][1005];
int n,m,k;
queue<node> q1[15];
queue<node> q2[15];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};
int bfs(int p){
    int newx=0;
    while(!q2[p].empty()){
        node x=q2[p].front();q2[p].pop();
        x.t=0;
        q1[p].push(x);
    }
    while(!q1[p].empty()){
        node x=q1[p].front();q1[p].pop();
        if(x.t==s[p]){
            q2[p].push(x);
            continue;
        }
        for(int i=0;i<4;i++){
            int xx=x.x+dx[i];
            int yy=x.y+dy[i];
            if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]=='#'||vis[xx][yy]||x.t+1>s[p]) continue;
            newx+=1;
            q1[p].push(node(xx,yy,x.t+1));
            vis[xx][yy]=p;
        }
    }
    if(newx>=1) return 1;
    else return 0;    
}
int ans[15];
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++) cin>>s[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]-'0'>=1&&a[i][j]-'0'<=9){
                vis[i][j]=a[i][j]-'0';
                q2[a[i][j]-'0'].push(node(i,j,0));
            }
        }
    }
    while(1){
        int flag=0;
        for(int i=1;i<=9;i++){
            flag+=bfs(i);
        }
        if(flag==0) break;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ans[vis[i][j]]+=1;
        }
    }
    for(int i=1;i<=k;i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}
View Code

题意:一个图,一群人,每个人有自己的速度。按顺序来占领空格子,有#的是墙。输出每个人占领的格子数量。速度的意思是从起点出发走一个格子需要1速度,走可以拐弯。轮到的时候占领的格子。其实也就是对于p每一次走的时候,曼哈顿距离<=s[p]的且未走过的可走点都算作是自己的。

思路:用bfs搭配结构体来做,挺考验代码功力的,q2队列是存对于p而言当前正在走且还未走到尽头的(即还可以走的)坐标以及离出发点的曼哈顿距离大小。q1队列存的是已经走到尽头的,即曼哈顿距离==s[p]的点,这个时候他们作为新的出发点,在这里一个一个将已走距离t更改为0。

有的时候,可能对于某个p,他可走的路被封死了,但是别的p还可以走,所以是:

while(还能走){
   int 已走的距离=0; 
   for(int i=1;i<=k;i++){
        已走的距离+=当前点i在该轮中走的距离; 
   }     
    如果已走的距离==0,意味着该轮大家都没有进展(即图满了),那么就结束了(说明大家都没的走了) 
}
原文地址:https://www.cnblogs.com/Anonytt/p/12859856.html