百度之星 2015 初赛(2) 1003 棋盘占领

棋盘占领

 
 Accepts: 937
 
 Submissions: 2201
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
Problem Description

百小度最近迷恋上了一款游戏,游戏里有一个n*m的棋盘,每个方格代表一个城池。
一开始的时候我们有g支军队,驻扎并占领了其中某些城池。然后我们可以在这些被占领城池的基础上,吞并占领周围的城池。


而其吞并占领的规则是这样的——一旦一个城池A相邻的上下左右四个城池中至少存在两个被占领,且这两个被占领的城池有公共点,那么城池A也将被占领。
比如我们用1表示初始的占领状态,0表示初始的未占领状态。
那么——


10

01

会最终会变成

11

11

而101则保持为101不变

现在告诉你一张地图一开始所有被占领城池的信息,问你最后多少个城池会被我们占领。

Input

第一行为T,表示输入数据组数。

下面T组数据,对于每组数据,
第一行是两个数 n,m(1n,m500) ,表示国土的大小为n*m。


第二行是一个整数 g(1g1000) ,表示我们一开始占领的城池数。
然后跟随g行,第i行一对整数 x,y(1xn,1ym) ,表示占领的第i个城池的坐标。 

Output

对第i组数据,输出

Case #i:

然后输出一行,仅包含一个整数,表示最终有多少个城池被占领。

Sample Input
4
2 2
2
1 1
2 2
3 3
3
1 1
2 3
3 2
2 4
5
1 1
1 1
1 2
1 3
1 4
2 4
2
1 1
2 4
Sample Output
Case #1:
4
Case #2:
9
Case #3:
4
Case #4:
2
解题思路:

用模拟的方法,维持一个队列和一个矩阵,将初始点全部输入队列中,矩阵对应被占领城池标记为1,未占领标记为0。

以后每一趟检查每个点的四个斜角处,如果有点,将对应的 2 X 2 区域填满,并将新占领的点压入队列。检查完毕后,将检查的点推出队列。

此题还存在更好的算法。

#include <iostream>
#include <queue>
#include <map>
using namespace std;

typedef pair<int ,int> point;

int main()
{
    int T;
    cin >> T;
    for(int i = 1; i <= T; i++) {
        int n, m, N, count = 0;
        queue<pair<int, int> > qp;
        cin >> n >> m >> N;
        bool a[n][m];
        for(int j = 0; j < n ; j++) {
            for(int k = 0; k < m; k++) {
                a[j][k] = false;
            }
        }
        for(int j = 0; j < N; j++) {
            point p;
            cin >> p.first >> p.second;
            p.first--;
            p.second--;
            qp.push(p);
            if(!a[p.first][p.second]) count++;
            a[p.first][p.second] = true;
        }

        while(!qp.empty()) {
            point p = qp.front();
            int x0 = p.first, y0 = p.second;
            int x = x0 - 1, y = y0 - 1;
            if(x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1) {
                if(a[x0 - 1][y0 - 1]) {
                    if(!a[x0-1][y0]) {
                        point p1(x0-1,y0);
                        qp.push(p1);
                        count++;
                        a[x0-1][y0] = true;
                    }
                    if(!a[x0][y0-1]) {
                        point p1(x0,y0-1);
                        qp.push(p1);
                        count++;
                        a[x0][y0-1] = true;
                    }
                }
            }
            x = x0 + 1, y = y0 - 1;
            if(x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1) {
                if(a[x0 + 1][y0 - 1]) {
                    if(!a[x0+1][y0]) {
                        point p1(x0+1,y0);
                        qp.push(p1);
                        count++;
                        a[x0+1][y0] = true;
                    }
                    if(!a[x0][y0-1]) {
                        point p1(x0,y0-1);
                        qp.push(p1);
                        count++;
                        a[x0][y0-1] = true;
                    }
                }
            }
            x = x0 - 1, y = y0 + 1;
            if(x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1) {
                if(a[x0 - 1][y0 + 1]) {
                    if(!a[x0-1][y0]) {
                        point p1(x0-1,y0);
                        qp.push(p1);
                        count++;
                        a[x0-1][y0] = true;
                    }
                    if(!a[x0][y0+1]) {
                        point p1(x0,y0+1);
                        qp.push(p1);
                        count++;
                        a[x0][y0+1] = true;
                    }
                }
            }
            x = x0 + 1, y = y0 + 1;
            if(x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1) {
                if(a[x0 + 1][y0 + 1]) {
                    if(!a[x0+1][y0]) {
                        point p1(x0+1,y0);
                        qp.push(p1);
                        count++;
                        a[x0+1][y0] = true;
                    }
                    if(!a[x0][y0+1]) {
                        point p1(x0,y0+1);
                        qp.push(p1);
                        count++;
                        a[x0][y0+1] = true;
                    }
                }
            }
            qp.pop();
        }
        cout << "Case #"<< i <<":" << endl;
        cout << count << endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值