[Luogu] 四子连棋

https://www.luogu.org/problemnew/show/P2346

广搜

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>

#define maxn 10010
#define inf 1000000007
#define ll long long

using namespace std;
int n, m, ans = inf;

int dx[5] = {0, 0, 1, -1, 0};
int dy[5] = {0, 1, 0, 0, -1};

struct Node {
    int a[5][5];
    int color;
    int step;
} t;

queue <Node> q;

bool check(Node f) {
    for(int i = 1; i <= 4; i ++) {
        if(f.a[i][1] == f.a[i][2] && f.a[i][1] == f.a[i][3] && f.a[i][1] == f.a[i][4]) return 1;
        if(f.a[1][i] == f.a[2][i] && f.a[1][i] == f.a[3][i] && f.a[1][i] == f.a[4][i]) return 1;
    }
    if(f.a[1][1] == f.a[2][2] && f.a[1][1] == f.a[3][3] && f.a[1][1] == f.a[4][4]) return 1;
    if(f.a[1][4] == f.a[3][2] && f.a[1][4] == f.a[2][3] && f.a[1][4] == f.a[4][1]) return 1;
    return 0;
}

void init() { //处理一开始的棋子颜色
    t.step = 0;
    t.color = 2;
    for(int i = 1; i <= 4; i ++)
        for(int j = 1; j <= 4; j ++)
            if(t.a[i][j] == 2)
                for(int k = 1; k <= 4; k ++) {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(t.a[x][y] == 2) continue ;
                    if(x >= 1 && x <= 4 && y >= 1 && y <= 4) { //注意边界
                        Node c = t;
                        c.color = t.a[x][y];
                        c.step = 1;
                        swap(c.a[i][j], c.a[x][y]);//移动棋子
                        q.push(c);
                    }
                }
}

void bfs() { //广搜模板
    while(!q.empty()) {
        Node b = q.front();
        q.pop();
        if(check(b)) {
            ans = b.step;
            return ;
        }
        for(int i = 1; i <= 4; i ++)
            for(int j = 1; j <= 4; j ++) {
                if(b.a[i][j] == 2) {
                    for(int k = 1; k <= 4; k ++) {
                        int x = i + dx[k];
                        int y = j + dy[k];
                        if(x >= 1 && x <= 4 && y >= 1 && y <= 4 && b.a[x][y] == (b.color ^ 1)) { //黑白交替移动
                            Node c = b;
                            swap(c.a[i][j], c.a[x][y]);//移动棋子
                            c.color = b.color ^ 1;//如果上一步走的是黑,这一步就是白,上一步是白,这一步是黑。
                            c.step = b.step + 1;//步数加一
                            q.push(c);//将当前状态入队
                        }
                    }
                }
            }
    }
}

int main() {
    int x, y, z;
    char s[10];
    for(int i = 1; i <= 4; i ++) {
        scanf("%s",s+1);
        for(int j = 1; j <= 4; j ++) { //处理图,便于广搜
            if(s[j] == 'B') t.a[i][j] = 1;
            if(s[j] == 'W') t.a[i][j] = 0;
            if(s[j] == 'O') t.a[i][j] = 2;
        }
    }
    init();
    bfs();
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2018-02-10 17:49  xayata  阅读(248)  评论(0编辑  收藏  举报