Codeforces H. Kilani and the Game(多源BFS)

题目描述:

Kilani and the Game

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Kilani is playing a game with his friends. This game can be represented as a grid of size n×m

, where each cell is either empty or blocked, and every player has one or more castles in some cells (there are no two castles in one cell).

The game is played in rounds. In each round players expand turn by turn: firstly, the first player expands, then the second player expands and so on. The expansion happens as follows: for each castle the player owns now, he tries to expand into the empty cells nearby. The player i

can expand from a cell with his castle to the empty cell if it's possible to reach it in at most (where s**i

Input

The first line contains three integers n, and p, 1≤p≤9

The second line contains p integers (1≤s≤109

The following n lines describe the game grid. Each of them consists of symbols, where '' denotes an empty cell, '' denotes a blocked cell and digit x) denotes the castle owned by player x

Output

Print p integers — the number of cells controlled by each player after the game ends.

Examples

Input

Copy

3 3 2
1 1
1..
...
..2

Output

Copy

6 3 

Input

Copy

3 4 4
1 1 1 1
....
#...
1234

Output

Copy

1 4 3 3 

Note

The picture below show the game before it started, the game after the first round and game after the second round in the first example:

img

In the second example, the first player is "blocked" so he will not capture new cells for the entire game. All other player will expand up during the first two rounds and in the third round only the second player will move to the left.

思路:

题目就是几个人玩游戏,拓展领地的游戏,每个人有一个最多移动步数,也就是从现有领地向外拓展的最大步数,一个人一个人拓展自己的领地,直到没有地方可拓展时游戏结束,输出每个人的领地大小。

刚开始时我用的DFS模拟,循环每个人,对每个人来说拓展自己的现有的且处于边界状态的格子。但是在十五个测试点的地方WA了,现在不知道是哪里写的不对。

然后改用BFS,维护一个向量,向量里的元素就是每个人的访问队列。每次访问过后,把边界状态(即步数用完的状态重新压入队列。用一个大循环,在其中这样模拟每个回合,一直下去直到所有玩家的访问后的边界状态的队列为空,也就是不会进行拓展时推出大循环。这里判断所有玩家是否均不可拓展有一点小trick,用一个标记flag(初始为0)记录是否退出大循环,另一个标记flag1(初始为一)记录每个玩家的可访问队列是否为空,为空置为0,每一个回合不断flag|=flag1,如果所有玩家不可拓展,即每个flag1=0,那么flag=0,这时候就可以退出大循环,游戏结束了。

注意的是刚开始我是直接修改原地图,最后扫一遍原地图做统计,但会超时好像(超了十几次,┓(;´_`)┏),因为每个点(除了每次出队的边界点)只能出队一次,出队且不为边界点的情况下统计即可,因为边界点到最后也会变成非边界点。

代码:

#include <iostream>
#include <vector>
#include <queue>
#include <memory.h>
#include <cstdio>
#define max_n 1005
using namespace std;
int n,m,p;
struct point
{
    int x;
    int y;
    int v;
};
vector<queue<point> > vec;
int speed[10];
char G[max_n][max_n];
int cnt[10];
int dirx[4] = {0,-1,0,1};
int diry[4] = {-1,0,1,0};
inline void extend(int x,int y,int id,int v)
{
    //cout << "x " << x << " y " << y << " id " << id << " v " << v << endl;
    for(int i = 0;i<4;i++)
    {
        int xx = x+dirx[i];
        int yy = y+diry[i];
        if(xx<0||xx>=n||yy<0||yy>=m||G[xx][yy]!='.')
        {
            continue;
        }
        else
        {
            char ch = id+'0';
            G[xx][yy] = ch;
            //cnt[id]++;
            point p;
            p.x = x+dirx[i];
            p.y = y+diry[i];
            p.v = v-1;
            vec[id].push(p);
        }
    }
}
#pragma optimize(3)
int main()
{
    cin >> n >> m >> p;
    queue<point> que;
    vec.push_back(que);
    for(int i = 1;i<=p;i++)
    {
        cin >> speed[i];
        queue<point> que;
        vec.push_back(que);
    }
    for(int i = 0;i<n;i++)
    {
        for(int j = 0;j<m;j++)
        {
            cin >> G[i][j];
            if('1'<=G[i][j]&&G[i][j]<='9')
            {
                point p;
                p.x = i;
                p.y = j;
                p.v = speed[G[i][j]-'0'];
                vec[G[i][j]-'0'].push(p);
            }
        }
    }
    int flag;
    queue<point> que2;
    while(1)
    {
        flag = 0;
        //cout << flag << endl;
        for(int i = 1; i<=p; i++)
        {
            int flag1 = 1;
            while(!vec[i].empty())
            {
                point p = vec[i].front();
                vec[i].pop();
                if(p.v==0)
                {
                    p.v = speed[i];
                    que2.push(p);
                    continue;
                }
                int x = p.x;
                int y = p.y;
                int v = p.v;
                cnt[i]++;
                extend(x,y,i,v);
            }
            if(que2.empty())
            {
                flag1 = 0;
            }
            while(!que2.empty())
            {
                point p = que2.front();
                que2.pop();
                vec[i].push(p);
            }
            /*for(int j = 0; j<n; j++)
            {
                for(int k = 0; k<m; k++)
                {
                    cout << G[j][k] << " ";
                }
                cout << endl;
            }
            cout << endl;*/
            flag|=flag1;
        }
        if(flag==0)
        {
            break;
        }
    }
    for(int i = 1;i<=p;i++)
    {
        cout << cnt[i] << " ";
    }
    cout << endl;
    return 0;
}
posted @ 2019-08-16 13:57  小张人  阅读(303)  评论(0编辑  收藏  举报
分享到: