题目大意:
一个棋盘,p种颜色已经涂了一些区域,每种颜色有扩散速度 si ,每轮按顺序依次扩展,扩展区域为已有区域任意格走 si 次能到达的可涂色格子,且不能穿过其他颜色与不可涂色格,棋盘无可涂色区域游戏结束,输出各种颜色格子数。
思路:
用队列按顺序bfs即可实现依次涂色,每次涂色要走最多si步,所以再嵌套一个bfs来从已有格子向外扩展。
要确保扩展的尽可能大,应从边界向外扩展,同时每次扩展计算最少步数判断是否能扩展到更远。
用一个变量记录剩余可涂色格子,0时直接跳出bfs。(本来tle,加了这个才勉强过去(´Д`))
代码:
(题目意思一直没理解清楚,边wa边改写的贼丑(lll¬ω¬)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1020;
char mp[maxn][maxn];
bool vis[maxn][maxn];
int d[10][maxn][maxn];
int s[10],ans[10];
int n,m,p,last;
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
struct node{
int x,y,o,s; //o记录当前玩家,s记录剩余移动次数
node(){}
node(int x,int y,int o,int s)
{
this->x = x;
this->y = y;
this->o = o;
this->s = s;
}
};
vector<node> bg[10];
queue<node> qn,qn2;
void bfs2() //每格扩展的最大范围
{
while(!qn2.empty())
{
if(last == 0) return;
node now = qn2.front(); qn2.pop();
for(int i = 0; i < 4; i++)
{
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if(nx < 0 || nx >= n || ny < 0 || ny >=m) continue;
else
{
if(!vis[nx][ny])
{
ans[now.o]++;
vis[nx][ny] = true;
mp[nx][ny] = '0' + now.o;
d[now.o][nx][ny] = d[now.o][now.x][now.y] + 1;
node next(nx,ny,now.o,now.s-1);
if(d[now.o][nx][ny] % s[now.o] == 0) qn.push(next);
if(now.s > 1) qn2.push(next);
last--;
}
else if(mp[nx][ny] != '0' + now.o) continue;
else if(d[now.o][now.x][now.y] + 1 < d[now.o][nx][ny]) //从当前格过来步数更少能扩展到更远
{
node next(nx,ny,now.o,now.s-1);
d[now.o][nx][ny] = d[now.o][now.x][now.y] + 1;
if(now.s > 1) qn2.push(next);
}
}
}
}
}
void bfs() //按顺序扩展
{
while(!qn.empty())
{
node now = qn.front(); qn.pop();
node temp(now.x,now.y,now.o,s[now.o]);
while(!qn2.empty()) qn2.pop();
qn2.push(temp);
bfs2();
}
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
last = n * m;
for(int i = 1; i <= p; i++) scanf("%d",&s[i]);
for(int i = 0; i < n; i++) scanf("%s",mp[i]);
for(int i = 0 ; i < 10; i++) bg[i].clear();
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
memset(d,0x33,sizeof(d));
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(mp[i][j] != '.')
{
if(mp[i][j] != '#')
{
int t = mp[i][j] - '0';
ans[t]++;
d[t][i][j] = 0;
bg[t].push_back(node(i,j,t,s[t]));
}
vis[i][j] = true;
last--;
}
}
}
while(!qn.empty()) qn.pop();
for(int i = 1; i <= p; i++)
for(int j = 0; j < bg[i].size(); j++) qn.push(bg[i][j]); //按顺序加入棋盘上的已有城堡
bfs();
for(int i = 1; i <= p; i++) printf("%d ",ans[i]);
printf("\n");
}