D. Kilani and the Game(多源BFS)

题目来源:http://codeforces.com/contest/1105/problem/D

题意:编号为1-k的点在一张n*m的表格中依次扩散,每个结点有各自的扩散速度且只可以往上下左右四个方向扩散,表格中每个空白的区域只能被一个结点占领,求最后各个结点所占领的区域的数量。

解题思路:我们可以定义两个队列:que1,que2,que1存放源点的信息,每次取que1中编号相同的结点的信息加入剩余扩散的步数存放入que2中,对que2的结点进行BFS,这样就能保证结点的扩散顺序了。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
inline ll gcd(ll i,ll j){
    return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
    return i/gcd(i,j)*j;
}
const int maxn=1e3+5;
int vis[maxn][maxn];
int ans[maxn];
char mp[maxn][maxn];
int v[maxn];
int m,n,p;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool jug(int x,int y){
    if(x<0||x>=m||y<0||y>=n||vis[x][y]!=0||mp[x][y]!='.')
    return false;
    return true;
}
struct node{
    int x,y,id;
    node(){
        x=y=id=0;
    }
    node(int x,int y,int id):x(x),y(y),id(id){
    }
};
struct node1{
    int x,y,wi,id;
    node1(int x,int y,int wi,int id):x(x),y(y),wi(wi),id(id){
    }
    node1(){
        x=y=wi=id=0;
    }
};
queue<node> que;
void bfs(){
    while(!que.empty()){
        node tem=que.front();
        que.pop();
        queue<node1> que1;
        //cout<<tem.id<<endl;
        que1.push(node1(tem.x,tem.y,v[tem.id],tem.id));
        while(!que.empty()&&que.front().id==tem.id){
            que1.push(node1(que.front().x,que.front().y,v[tem.id],tem.id));//找到编号相同的点同时进行扩散
            que.pop();
        }
        while(!que1.empty()){
            node1 tem1;
            tem1=que1.front();
            que1.pop();
            int dx,dy;
            if(tem1.wi<=0){
                que.push(node(tem1.x,tem1.y,tem1.id));
                continue;
            }
            for(int i=0;i<4;i++){
                 dx=tem1.x+dir[i][0];
                 dy=tem1.y+dir[i][1];
                if(jug(dx,dy)){
                    vis[dx][dy]=tem1.id;
                    ans[tem1.id]++;
                    que1.push(node1(dx,dy,tem1.wi-1,tem1.id));
                }
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&m,&n,&p);
    for(int i=1;i<=p;i++){
        scanf("%d",&v[i]);
    }
    for(int i=0;i<m;i++){
        scanf("%s",mp[i]);
    }
    for(int i=1;i<=p;i++){
        for(int j=0;j<m;j++){
            for(int k=0;k<n;k++){
                if(mp[j][k]==i+'0'){
                    vis[j][k]=i;
                    ans[i]++;
                    que.push(node(j,k,i));//保证结点按顺序扩散
                }
            }
        }
    }
    bfs();
    /*for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(vis[i][j]==0){
                cout<<"#"<<" ";
            }
            else
            cout<<vis[i][j]<<" ";
        }
        cout<<endl;
    }*/
    for(int i=1;i<=p;i++){
        cout<<ans[i]<<" ";
    }
    return 0;
}

 

posted @ 2019-01-23 16:23  风雨兼程-zhi  阅读(291)  评论(0编辑  收藏  举报