题目链接 http://codeforces.com/contest/1105/problem/D
直接用两个队列模拟,一个队列(init)记住每一轮的起点,另一个队列(queuq)记住每一轮的扩张过程
4 4 2
2 2
1...
....
...2
比如这个样例
第一轮
第二轮
#include<bits/stdc++.h>
using namespace std;
int velocity[10], ans[10];
int d[5][2] = {{0,-1},{0,1},{1,0},{-1,0}};
string mapp[1005];
struct node {
int x, y, step;
};
queue<node>init,queuq;
int main(){
std::ios::sync_with_stdio(false);
int n, m, p, i, k, j;
while(cin >> n >> m >> p){
while(!init.empty())init.pop();//用过的队列清空
while(!queuq.empty())queuq.pop();
memset(ans, 0, sizeof(ans));
for(i = 1; i <= p; i++){
cin >> velocity[i];
}
for(i = 0; i < n; i++){
cin >> mapp[i];
}
for(k = 1; k <= p; k++){
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){//查找初始玩家拥有的地产,入队
if(mapp[i][j] == '0'+k){
ans[k]++;
node temp;
temp.x = i;
temp.y = j;
temp.step = 0;//这个是记住当前走了多少步,不要超过他的限制
init.push(temp);
}
}
}
}
//开始模拟
while(!init.empty()){
node temp = init.front();
init.pop();
int num = mapp[temp.x][temp.y]-'0';
for(i = 0; i < 4; i++){//速度至少为1 就先走一步,且全部入队列queuq
node v;
v.x = temp.x+d[i][0];
v.y = temp.y+d[i][1];
if(v.x<n && v.x >=0 && v.y < m && v.y>=0 && mapp[v.x][v.y]=='.'){
ans[num]++;
v.step = temp.step+1;//更新一下当前的步数
mapp[v.x][v.y] = mapp[temp.x][temp.y];
queuq.push(v);//入队列
}
}
while(!queuq.empty()){
node temp = queuq.front();
queuq.pop();
int num = mapp[temp.x][temp.y]-'0';
node temp1;
if(temp.step == velocity[num]){//如果已经达到步数了,作为下一轮比赛的起点,入队列init
temp1 = temp;
temp1.step = 0;//更新步数
init.push(temp1);
continue;
}
for(i = 0; i < 4; i++){//一直走,直到达到速度,或无法再扩张
node v;
v.x = temp.x+d[i][0];
v.y = temp.y+d[i][1];
if(v.x<n && v.x >=0 && v.y < m && v.y>=0 && mapp[v.x][v.y]=='.' && temp.step+1 <= velocity[num]){
ans[num]++;
v.step = temp.step+1;
mapp[v.x][v.y] = mapp[temp.x][temp.y];
queuq.push(v);
}
}
}
}
cout << ans[1] ;
for(k = 2; k <= p; k++){
cout << " " << ans[k] ;
}
cout << endl;
}
return 0;
}