题目: http://codeforces.com/contest/1105/problem/D
题意:
n*m的格子,p个人,每个人有若干个堡垒;
每次从1~p轮流行动,一次行动中每个人从已经占领的格子往外走s[p]步能到的格子会全部占领,问结束后每个人能占领多少个格子。
分析:
bfs,注意这种bfs的写法。
每个人有一个队列border[i],保存每次扩展后最外围的节点;
另有一个队列Q用来普通bfs,每次从border[i]的节点开始扩展;
轮流扩展每个人:for(i) expand(i);
队列中保存位置信息和走过多少步node{x,y,step};
普通队列Q中step=0的节点加入border中;
不能扩展则退出。
代码:
//jerry99
#include <bits/stdc++.h>
using namespace std;
typedef long long llong;
const int tmax=1005;
int n,m,p,vis[tmax][tmax],ans[tmax],s[tmax];
char a[tmax][tmax];
struct node{
int xx,yy,step;
};
queue<node> border[10],Q;
int dx[5]={0,-1,1,0,0},
dy[5]={0,0,0,-1,1};
void bfs(int who)
{
node tmp;
int x,y,i;
while(!Q.empty())
{
tmp=Q.front();
Q.pop();
if(tmp.step==0) border[who].push(tmp);
else for(i=1;i<=4;i++)
{
x=tmp.xx+dx[i];
y=tmp.yy+dy[i];
if(x<1||x>n||y<1||y>m||a[x][y]!='.'||vis[x][y]!=0) continue;
vis[x][y]=who;
Q.push(node{x,y,tmp.step-1});
}
}
return;
}
bool expand(int who)
{
node tmp;
while(!border[who].empty())
{
tmp=border[who].front();
border[who].pop();
tmp.step=s[who];
Q.push(tmp);
}
bfs(who);
return !border[who].empty();
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
int i,j,num;
for(i=1;i<=p;i++)
scanf("%d",&s[i]);
for(i=1;i<=n;i++)
scanf("%s",a[i]+1);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i][j]>='0'&&a[i][j]<='0'+p)
{
num=a[i][j]-'0';
border[num].push(node{i,j,s[num]});
vis[i][j]=num;
}
}
while(1)
{
bool ok=false;
for(i=1;i<=p;i++)
ok|=expand(i);
if(!ok) break;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
ans[vis[i][j]]++;
for(i=1;i<=p;i++)
printf("%d ",ans[i]);
return 0;
}