2017-2018 ACM-ICPC, Asia Daejeon Regional Contest:Gym 101667B

題目鏈接:https://codeforces.com/gym/101667/attachments

題意:有一個444*4的棋盤下三子棋,下棋規則是黑白兩方輪流選擇某一列,在這一列按行從小到大開始找,找到第一個沒有被佔據的位置然後將棋子放下,當出現三子連環的時候棋局結束。現在已知黑棋先手,並且知道第一手下在了第xx列。問當白棋下在(a,b)(a,b)位置並且這個時候勝利的情況有多少種滿足要求的棋局。

解題心得:因爲棋局很小並且限制條件題目中也給出了可以直接暴力搜索主要注意一下判斷是否勝利的三子連環的情況。



#include <bits/stdc++.h>

using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
int maps[10][10], a, b, x, r[10];
set<ull> se;

bool checke(int x, int y, int c)//判斷當前棋子顏色爲c下在(x,y)位置是否勝利
{
    if(x - 1 >= 1 && x + 1 <= 4){
        if(maps[x - 1][y] == c && maps[x + 1][y] == c) return false;
    }
    if(y - 1 >= 1 && y + 1 <= 4){
        if(maps[x][y - 1] == c && maps[x][y + 1] == c) return false;
    }
    if(x - 1 >= 1 && y + 1 <= 4 && x + 1 <= 4 && y - 1 >= 1){
        if(maps[x - 1][y + 1] == c && maps[x + 1][y - 1] == c) return false;
    }
    if(x - 1 >= 1 && y - 1 >= 1 && x + 1 <= 4 && y + 1 <= 4){
        if(maps[x - 1][y - 1] == c && maps[x + 1][y + 1] == c) return false;
    }
    if(x - 2 >= 1){
        if(maps[x - 1][y] == c && maps[x - 2][y] == c) return false;
    }
    if(x + 2 <= 4){
        if(maps[x + 1][y] == c && maps[x + 2][y] == c) return false;
    }
    if(y - 2 >= 1){
        if(maps[x][y - 1] == c && maps[x][y - 2] == c) return false;
    }
    if(y + 2 <= 4){
        if(maps[x][y + 1] == c && maps[x][y + 2] == c) return false;
    }
    if(x - 2 >= 1 && y + 2 <= 4){
        if(maps[x - 1][y + 1] == c && maps[x - 2][y + 2] == c) return false;
    }
    if(x - 2 >= 1 && y - 2 >= 1){
        if(maps[x - 1][y - 1] == c && maps[x - 2][y - 2] == c) return false;
    }
    if(x + 2 <= 4 && y - 2 >= 1){
        if(maps[x + 1][y - 1] == c && maps[x + 2][y - 2] == c) return false;
    }

    if(x + 2 <= 4 && y + 2 <= 4){
        if(maps[x + 1][y + 1] == c && maps[x + 2][y + 2] == c) return false;
    }

    return true;
}

ull Hash() {//將棋局hash存儲去重
    ull sum = 1;
    for(int i=1;i<=4;i++) {
        for(int j=1;j<=4;j++) {
            ull va = maps[i][j];
            if(va == -1) va = 2333;
            sum = sum*233 + va;
        }
    }
    return sum;
}

void dfs(int r1, int r2, int r3, int r4, int w)//暴力搜索,分別記錄每一列已將放下的棋子數以及當前棋子的顏色
{
    if((r1 == a && b == 1) || (r2 == a && b == 2) || (r3 == a && b == 3) || (r4 == a && b == 4)) return ;
    if(r1 > 4 || r2 > 4 || r3 > 4 || r4 > 4) return;
    if(checke(r1 + 1, 1,w)){
        maps[r1 + 1][1] = w;
        dfs(r1 + 1, r2, r3, r4, !w);
        maps[r1 + 1][1] = -1;
    } else{
        if(r1 + 1 == a && 1 == b && w == 1){
            se.insert(Hash());
        }
    }
    if(checke(r2 + 1, 2, w)){
        maps[r2 + 1][2] = w;
        dfs(r1, r2 + 1, r3, r4, !w);
        maps[r2 + 1][2] = -1;
    } else {
        if(r2 + 1 == a && 2 == b && w == 1){
            se.insert(Hash());
        }
    }
    if(checke(r3 + 1, 3, w )){
        maps[r3 + 1][3] = w;
        dfs(r1, r2, r3 + 1, r4, !w);
        maps[r3 + 1][3] = -1;
    } else {
        if(r3 + 1 == a && 3 == b && w == 1){
            se.insert(Hash());
        }
    }
    if(checke(r4 + 1, 4, w)){
        maps[r4 + 1][4] = w;
        dfs(r1, r2, r3, r4 + 1, !w);
        maps[r4 + 1][4] = -1;
    } else {
        if(r4 + 1 == a && 4 == b && w == 1){
            se.insert(Hash());
        }
    }
}

int main()
{
    scanf("%d%d%d", &x, &a, &b);
    memset(maps, -1, sizeof maps);
    maps[1][x] = 0;
    r[x]++;

    dfs(r[1], r[2], r[3], r[4], 1);
    printf("%d\n", int(se.size()));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章