https://codeforces.com/problemset/problem/1105/D
题目大意:
n
∗
m
n*m
n∗m的地图,
p
p
p个人,每个人有若干个堡垒;
p
p
p个人每次从
1
1
1开始轮流行动,一次行动中第
i
i
i个人从他已经占领的格子往外走
s
p
[
i
]
sp[i]
sp[i]步能到的格子都会被他占领。当没有格子可以再被占领时游戏结束,问结束后每个人各占领了多少个格子。
题目大意:多源 b f s bfs bfs,用队列数组就可以了。因为每次扩张都是从已经占领的点向四周扩散,因此下次扩张只需要从边界扩张就可以了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define pr pair<long long,int>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1005;
struct node
{
int x,y,step;
node(){}
node(int xx,int yy,int ss)
{
x=xx,y=yy,step=ss;
}
};
int n,m,p,op;
char s[maxn][maxn];
int vis[maxn][maxn];
int sp[15],ans[15];
int d[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
bool flag=0;
queue<node> q[15];
node tmp[maxn*maxn];
void solve()
{
node t;
int len,dx,dy;
while(1)
{
flag=0;
for(int i=1;i<=p;i++)
{
len=0;
while(!q[i].empty())
{
t=q[i].front();
q[i].pop();
if(t.step==0)
{
t.step=sp[i];
tmp[len++]=t;
continue;
}
for(int j=0;j<4;j++)
{
dx=t.x+d[j][0];
dy=t.y+d[j][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&!vis[dx][dy]&&s[dx][dy]!='#'&&t.step)
q[i].push(node(dx,dy,t.step-1)),vis[dx][dy]=i,flag=1;
}
}
for(int j=0;j<len;j++)
q[i].push(tmp[j]);
}
if(!flag)
break;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
ans[vis[i][j]]++;
for(int i=1;i<=p;i++)
printf("%d ",ans[i]);
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=p;i++)
scanf("%d",&sp[i]);
for(int i=0;i<n;i++)
scanf("%s",s[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(s[i][j]>='1'&&s[i][j]<='9')
q[s[i][j]-'0'].push(node(i,j,sp[s[i][j]-'0'])),vis[i][j]=s[i][j]-'0';
solve();
return 0;
}