CodeForces 1105D Kilani and the Game (搜索bfs)

题目大意:

一个棋盘,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");
}
发布了28 篇原创文章 · 获赞 8 · 访问量 2802

猜你喜欢

转载自blog.csdn.net/IuSpet/article/details/86600478
今日推荐