HDU 5556 Ancient Go 模拟

链接

HDU 5556 Ancient Go

题意

8x8的围棋,x为黑, o为白,当前下黑子能否至少提出一颗白子

思路

其实这题没必要写一篇博客的,是简单的模拟。可是近段时间对围棋比较感兴趣吧,印象中这是第一次写围棋相关的题目,正好AlphaGo现在正在舆论的风口浪尖,所以还是留存一下此题吧。

代码

#include <bits/stdc++.h>
#define LL long long
#define MAXN 15
using namespace std;

const int step[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
struct Node{
    int x, y;
};
int a[MAXN][MAXN];
char ss[MAXN][MAXN];
bool vis[MAXN][MAXN], mp[MAXN][MAXN];
bool done[105], is_die[105];

void bfs(int p, int q, int flag){
    queue<Node> Q;
    Node s, t;
    s.x = p;
    s.y = q;
    Q.push(s);
    a[p][q] = flag;
    while(!Q.empty()){
        s = Q.front(), Q.pop();
        for(int i = 0; i < 4; ++i){
            t.x = s.x + step[i][0];
            t.y = s.y + step[i][1];
            if(t.x < 1 || t.x > 9 || t.y < 1 || t.y > 9) continue;
            if(ss[t.x][t.y] == '.' || ss[s.x][s.y] != ss[t.x][t.y]) continue;
            if(vis[t.x][t.y]) continue;
            Q.push(t);
            vis[t.x][t.y] = true;
            a[t.x][t.y] = flag;
        }
    }
}
int find_eye(int p, int q){
    queue<Node> Q;
    memset(mp, 0, sizeof(mp));
    Node s, t;
    s.x = p;
    s.y = q;
    Q.push(s);
    mp[p][q] = true;
    int res = 0;
    while(!Q.empty()){
        s = Q.front(), Q.pop();
        for(int i = 0; i < 4; ++i){
            t.x = s.x + step[i][0];
            t.y = s.y + step[i][1];
            if(t.x < 1 || t.x > 9 || t.y < 1 || t.y > 9 || mp[t.x][t.y]) continue;
            mp[t.x][t.y] = true;
            if(ss[t.x][t.y] == '.'){
                ++res;
                continue;
            }
            if(ss[t.x][t.y] == ss[s.x][s.y]){
                Q.push(t);
            }
        }
    }
    return res;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int T;
    int cas = 0;
    scanf("%d", &T);
    while(T--){
        for(int i = 1; i <= 9; ++i){
            scanf("%s", ss[i] + 1);
        }
        //找出连通块
        memset(vis, 0, sizeof(vis));
        int flag = 1;
        for(int i = 1; i <= 9; ++i){
            for(int j = 1; j <= 9; ++j){
                if(!vis[i][j] && ss[i][j] != '.'){
                    bfs(i, j, flag++);
                }
                //printf("%5d", a[i][j]);
            }
           // printf("\n");
        }
        //提对方死棋
        memset(done, 0, sizeof(done));
        for(int i = 1; i <= 9; ++i){
            for(int j = 1; j <= 9; ++j){
                if(is_die[a[i][j]]){
                    ss[i][j] = '.';
                    continue;
                }
                if(done[a[i][j]]) continue;
                if(ss[i][j] != 'o') continue;
                int num = find_eye(i, j);
                done[a[i][j]] = true;
                if(num == 0){
                    is_die[a[i][j]] = true;
                    ss[i][j] = '.';
                }
            }
        }

        //提己方死棋
        memset(done, 0, sizeof(done));
        for(int i = 1; i <= 9; ++i){
            for(int j = 1; j <= 9; ++j){
                if(is_die[a[i][j]]){
                    ss[i][j] = '.';
                    continue;
                }
                if(done[a[i][j]]) continue;
                if(ss[i][j] != 'x') continue;
                int num = find_eye(i, j);
                done[a[i][j]] = true;
                if(num == 0){
                    is_die[a[i][j]] = true;
                    ss[i][j] = '.';
                }
            }
        }

        //提子后计算对方气
        memset(done, 0, sizeof(done));
        bool ans = false;
        for(int i = 1; i <= 9; ++i){
            for(int j = 1; j <= 9; ++j){
                if(done[a[i][j]]) continue;
                if(ss[i][j] != 'o') continue;
                int num = find_eye(i, j);
                done[a[i][j]] = true;
                if(num == 1){
                    ans = true;
                    break;
                }
            }
            if(ans) break;
        }
        if(ans){
            printf("Case #%d: Can kill in one move!!!\n", ++cas);
        }
        else{
            printf("Case #%d: Can not kill in one move!!!\n", ++cas);
        }
    }
}

查看原文:http://www.macinchang.com/2016/02/21/551/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值