(CodeForces) D. Kilani and the Game (搜索)

视频讲解戳这里

传送门

题目大意:一个n*m的图,有空格子'.',也有障碍物'#',也有各个玩家的城堡,编号对应着玩家的编号1,2,3.....;每个玩家轮流开始,有他城堡的地方就可以向上下左右扩散,而且分别有一个扩散的速度si,也就是一次可以往外扩散si层,当所有玩家都不能动时,问各个玩家所有的城堡数。

解题思路:思路还是很清晰的,就是每一轮对每一个玩家宽搜一次,每个玩家宽搜si层,往外宽搜一层就是将现在队列里的元素清空一次。题目还有一个坑点就是它的si有1e9的范围,对于这种用max(m,n)代替就行了,不然会T。其他细节剪枝扣扣就行了。代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=1e3+5;
int n,m,p,mp[maxn][maxn],sp[15];
struct node {
	int x;
	int y;
};
queue<node> q[15];
int allnum=0; //记录已经被占领的格子
int ans[15];
int dx[]= {1,0,0,-1};
int dy[]= {0,1,-1,0};
void pbfs(int np) { //每个玩家的宽搜
	int prenum=allnum;
	for(int i=1; i<=sp[np]; ++i) {
		int msize=q[np].size();
		prenum=allnum;
		while(msize) {
			msize--;
			node nt=q[np].front();
			q[np].pop();
			int nx=nt.x,ny=nt.y;
			for(int i=0; i<4; ++i) {
				int tx=nx+dx[i],ty=ny+dy[i];
				if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&mp[tx][ty]==0) {
					allnum++;
					mp[tx][ty]=np;
					q[np].push(node {tx,ty});
					ans[np]++;
				}
			}	
		}
		if(prenum==allnum)	break;
	}
}
void bfs() { //控制游戏的轮数
	if(allnum==n*m)	return;
	int prenum=allnum;
	for(int i=1; i<=p; ++i) {
		if(ans[i])	pbfs(i);
	}
	if(allnum==prenum)	return;
	bfs();
}
int main() {
	std::ios::sync_with_stdio(0);
	cin>>n>>m>>p;
	int ms=max(n,m);
	for(int i=1; i<=p; ++i) {
		cin>>sp[i];
		sp[i]=min(sp[i],ms);
	}
	char tp;
	for(int i=1; i<=n; ++i) {
		for(int j=1; j<=m; ++j) {
			cin>>tp;
			if(tp=='.')	{
				mp[i][j]=0;
				continue;
			}
			if(tp=='#') {
				mp[i][j]=-1;
				allnum++;
				continue;	
			}
			int t=tp-'0';
			mp[i][j]=t;
			q[t].push(node {i,j});
			allnum++;
			ans[t]++;
		}
	}
	bfs();
	for(int i=1; i<=p; ++i) {
		cout<<ans[i]<<" ";
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/86571547