视频讲解戳这里
题目大意:一个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;
}