Codeforces 1105D(Kilani and the Game,双队列bfs)
AC代码:
#include<bits/stdc++.h> #define ll long long #define endl '\n' #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; }
题意:一个图,一群人,每个人有自己的速度。按顺序来占领空格子,有#的是墙。输出每个人占领的格子数量。速度的意思是从起点出发走一个格子需要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,意味着该轮大家都没有进展(即图满了),那么就结束了(说明大家都没的走了) }
前ICPC算法竞赛退役选手|现摸鱼ing