【POJ】Flip Game

题目传送门

本题知识点:深度优先搜索 + 暴力枚举 + 回溯

本题题意比较简单,要求把棋盘的棋子翻成同一颜色的,如果可以就输出最少步数,否则“Impossible”。

样例4步最快的就是把棋子都翻成white('w'),此时我犯了一个严重的错误。

在草稿纸上我的四步是这样走的:

第一步:翻 (1,1)

第二步:翻 (1,3)

第三步:翻 (2,2)

第四步:翻 (2,4)

//   1 2 3 4
// 1 b w w b
// 2 b b w b
// 3 b w w b
// 4 b w w w

于是我一整天的思路是:遍历16个点,然后每次遍历时重新从(1,1)这个点开始搜。

喵喵喵?那这样1s真的可以吗?

当然不行!

在花了一上午的时间后,我终于按耐不住看了其他大牛的题解,才发现自己以上的思路重复了。对!以上四步,无论哪步先走,效果都是一样的!

因此,我们只需要从 (1,1) 搜到 (4,4) 即可

搜的时候有两种状态,翻与不翻

例如:样例中, (1,1) 是翻了的,接着到 (2,2) 才翻,换句话说,(1,2) (1,3) (1,4) (2,1) 这些点都是没有翻的。

要注意的一点是,翻的棋子未必是正确的棋子,因此我们翻完之后还需要把它翻回原状(这就是回溯思想)

最后我们每次都查一下是否都是黑棋或者是白棋都行了。

(附上AC代码以及自己之前写的又长又臭的代码)

//// POJ 1753
#include<iostream>
#include<cstdio>
using namespace std;

char chess[10][10];
int ans = 0x3f3f3f3f, cnt;

void init(){
    for(int i = 0; i < 10; i++){
        for(int j = 0; j < 10; j++){
            chess[i][j] = 'a';
        }
    }
}

bool check(){
    bool can = true;
    char ch = chess[1][1];
    for(int i = 1; i <= 4; i++){
        for(int j = 1; j <= 4; j++){
            if(ch != chess[i][j]){
                can = false;
                return can;
            }
        }
    }
    return can;
}

void turn(int h, int w){ 
    // mid
    if(chess[h][w] == 'b') chess[h][w] = 'w';
    else chess[h][w] = 'b';
    // up
    if(chess[h + 1][w] == 'b') chess[h + 1][w] = 'w';
    else if(chess[h + 1][w] == 'w') chess[h + 1][w] = 'b';
    // right
    if(chess[h][w + 1] == 'b') chess[h][w + 1] = 'w';
    else if(chess[h][w + 1] == 'w') chess[h][w + 1] = 'b';
    // down
    if(chess[h - 1][w] == 'b') chess[h - 1][w] = 'w';
    else if(chess[h - 1][w] == 'w') chess[h - 1][w] = 'b';
    // left
    if(chess[h][w - 1] == 'b') chess[h][w - 1] = 'w';
    else if(chess[h][w - 1] == 'w') chess[h][w - 1] = 'b';
}

void dfs(int h, int w, int cnt){
    if(check()){ // check
        if(cnt < ans) ans = cnt;
        return ;
    }
    if(h == 5) return ;

    // 翻它
    turn(h, w); // change
    if(w == 4) dfs(h + 1, 1, cnt + 1); // 换行
    else dfs(h, w + 1, cnt + 1);
    turn(h, w); // back 翻回来

    // 不翻不翻
    if(w == 4) dfs(h + 1, 1, cnt);
    else dfs(h, w + 1, cnt);
}
int main()
{
    init();
    for(int i = 1; i <= 4; i++){
        scanf("%s", chess[i] + 1);
    }
    dfs(1, 1, 0);
    if(ans != 0x3f3f3f3f) printf("%d\n", ans);
    else printf("Impossible\n");
    return 0;
}
//#include<iostream>
//#include<cstdio>
//#include<cstring>
//using namespace std;
//
//char first[10][10];
//char chess[10][10];
//bool take[10][10];
//int ans = 0x3f3f3f3f, cnt;
//int black, white, B, W;
//
//void init(){
//    for(int i = 0; i <= 5; i++){
//        for(int j = 0; j <= 5; j++){
//            first[i][j] = 'a';
//        }
//    }
//}
//
//void show(){
//    for(int i = 1; i <= 4; i++){
//        printf("%s\n", chess[i] + 1);
//
//    } putchar('\n');
//}
//
//void save(){
//    for(int i = 0; i <= 5; i++){
//        for(int j = 0; j <= 5; j++){
//            chess[i][j] = first[i][j];
//        }
//    }
//}
//
//bool check(){
//    bool can = true;
//    char ch = chess[1][1];
//    for(int i = 1; i <= 4; i++){
//        for(int j = 1; j <= 4; j++){
//            if(ch != chess[i][j]){
//                can = false;
//            }
//        }
//    }
//    return can;
//}
//
//void turn(int h, int w){
//    // up
//    if(chess[h + 1][w] == 'b') chess[h + 1][w] = 'w';
//    else if(chess[h + 1][w] == 'w') chess[h + 1][w] = 'b';
//    // right
//    if(chess[h][w + 1] == 'b') chess[h][w + 1] = 'w';
//    else if(chess[h][w + 1] == 'w') chess[h][w + 1] = 'b';
//    // down
//    if(chess[h - 1][w] == 'b') chess[h - 1][w] = 'w';
//    else if(chess[h - 1][w] == 'w') chess[h - 1][w] = 'b';
//    // left
//    if(chess[h][w - 1] == 'b') chess[h][w - 1] = 'w';
//    else if(chess[h][w - 1] == 'w') chess[h][w - 1] = 'b';
//}
//
//void back(int h, int w){
//    // up
//    if(chess[h + 1][w] == 'b') chess[h + 1][w] = 'w';
//    else if(chess[h + 1][w] == 'w') chess[h + 1][w] = 'b';
//    // right
//    if(chess[h][w + 1] == 'b') chess[h][w + 1] = 'w';
//    else if(chess[h][w + 1] == 'w') chess[h][w + 1] = 'b';
//    // down
//    if(chess[h - 1][w] == 'b') chess[h - 1][w] = 'w';
//    else if(chess[h - 1][w] == 'w') chess[h - 1][w] = 'b';
//    // left
//    if(chess[h][w - 1] == 'b') chess[h][w - 1] = 'w';
//    else if(chess[h][w - 1] == 'w') chess[h][w - 1] = 'b';
//}
//
//void solve_white(int h, int w){
//    cnt++;
//    // mid
//    chess[h][w] = 'w';
//    white++; black--;
//    turn(h, w);
//
//    if(check()){
//        if(cnt < ans) ans = cnt;
////        show();
//        return ;
//    }
//
//    for(int i = 1; i <= 4; i++){
//        for(int j = 1; j <= 4; j++){
//            if(chess[i][j] == 'b' && !take[i][j]){
//                take[i][j] = true;
//                solve_white(i, j);
//                take[i][j] = false;
//                cnt--;
//                chess[i][j] = 'b';
//                back(i, j);
//            }
//        }
//    }
//}
//
//void solve_black(int h, int w){
//    cnt++;
//    // mid
//    chess[h][w] = 'b';
//    black++; white--;
//    turn(h, w);
//
//    if(check()){
//        if(cnt < ans) ans = cnt;
////        show();
//        return ;
//    }
//
//    for(int i = 1; i <= 4; i++){
//        for(int j = 1; j <= 4; j++){
//            if(chess[i][j] == 'w' && !take[i][j]){
//                take[i][j] = true;
//                solve_white(i, j);
//                take[i][j] = false;
//                cnt--;
//                chess[i][j] = 'w';
//                back(i, j);
//            }
//        }
//    }
//}
//
//int main()
//{
//    init();
//    for(int i = 1; i <= 4; i++){
//        scanf("%s", first[i] + 1);
//    }
//
//    save();
//    if(check()){
//        printf("%d\n", 0);
//        return 0;
//    }
//
//    // turn white is all
//    for(int i = 1; i <= 4; i++){
//        for(int j = 1; j <= 4; j++){
//            if(chess[i][j] == 'b'){
//                cnt = 0;
//                black = B; white = W;
//                take[i][j] = true;
//                solve_white(i, j);
//                memset(take, false, sizeof(take));
//                save();
////                printf("i:%d j:%d ans:%d\n", i, j, ans);
//            }
//        }
//    }
//    printf("white %d\n", ans);
//
//    save();
//    memset(take, false, sizeof(take));
//    // turn black is all
//    for(int i = 1; i <= 4; i++){
//        for(int j = 1; j <= 4; j++){
//            if(chess[i][j] == 'w'){
//                cnt = 0;
//                black = B; white = W;
//                take[i][j] = true;
//                solve_black(i, j);
//                memset(take, false, sizeof(take));
//                save();
////                printf("i:%d j:%d ans:%d\n", i, j, ans);
//            }
//        }
//    }
//
//    if(ans == 0x3f3f3f3f) printf("Impossible\n");
//    else printf("%d\n", ans);
//
//    return 0;
//}

猜你喜欢

转载自www.cnblogs.com/Ayanowww/p/11526684.html