POJ 1753

确定第一行之后,剩下的几行递推即可,再判断最后一行是否全部一样

Acwing95. 费解的开关 的区别在于,这个题目正面或者反面都可以,写一个 work 函数,传两遍参数就行了

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 6,INF = 0x3f3f3f3f;
int g[N][N],backup[N][N];
void turn(int x,int y) {
    g[x][y] ^= 1;
    g[x + 1][y] ^= 1;
    g[x - 1][y] ^= 1;
    g[x][y + 1] ^= 1;
    g[x][y - 1] ^= 1;
}
int work(int flag) {
    int ans = INF;
    for(int op = 0;op < 1 << 4; ++op) {
        memcpy(backup,g,sizeof g);
        int step = 0;
        for(int i = 0;i < 4; ++i) {// 枚举第一行操作
            if(op >> i & 1) {
                step ++;
                turn(1,i + 1);
            }
        }
        for(int i = 1;i <= 3; ++i) {
            for(int j = 1;j <= 4; ++j) {
                if(g[i][j] != flag) {
                    step ++;
                    turn(i + 1,j);
                }
            }
        }
        bool ok = 1;
        for(int i = 1;i <= 4; ++i) {
            if(g[4][i] != flag) {
                ok = 0;
                break;
            }
        }
        if(ok) ans = min(ans,step);
        memcpy(g,backup,sizeof g);
    }
    return ans;
}
int main() {
    char ch;
    for(int i = 1;i <= 4; ++i) {
        for(int j = 1;j <= 4; ++j) {
            cin >> ch;
            if(ch == 'w') g[i][j] = 1;
            else g[i][j] = 0;
        }
    }
    int ans = min(work(0),work(1));
    if(ans == INF) cout << "Impossible" << endl;
    else cout << ans << endl;
    return 0;
}

映射到一维数组上

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define endl '\n'
const int N = 5;
const int INF = 0x3f3f3f3f;
char g[N][N],backup[N][N];
int ans = INF;
int dx[5] = {0,0,0,1,-1};// x方向数组
int dy[5] = {0,1,-1,0,0};// y方向数组
void turn_all(int x,int y) {/
    for(int i = 0;i < 5; ++i){//改变5个方向
        int nx = x + dx[i],ny = y + dy[i];
        if(nx < 0 || nx >= 4 || ny < 0 || ny >= 4) continue;//如果越界了就不操作
        if(g[nx][ny] == 'b') g[nx][ny] = 'w';
        else g[nx][ny] = 'b';
    }
}
int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    for(int i = 0;i < 4; ++i) cin >> g[i];
    for(int op = 0;op < (1 << 16); ++op) {
        int step = 0;
        bool flag = 0;
        memcpy(backup,g,sizeof g);//备份棋盘
        for(int i = 0;i < 4; ++i) {// 位运算枚举子集
            for(int j = 0;j < 4; ++j) {
                if(op >> (i * 4 + j) & 1) {//判断 第 i*4 + j 位是否位 1
                    turn_all(i,j);
                    step ++;
                }
            }
        }
        for(int i = 0;i < 4; ++i) {// 判断棋子是否全部为一种颜色
            for(int j = 0;j < 4; ++j) {
                if(g[i][j] != g[0][0]) {
                    flag = 1;
                    break;
                }
            }
            if(flag) break;
        }
        if(flag == 0) ans = min(ans,step);// 如果全部同色,更新答案
        memcpy(g,backup,sizeof g);// 还原棋盘
    }
    if(ans == INF) cout << "Impossible";// 如果答案没有被更新,输出Impossible
    else cout << ans;
    return 0;
}
posted @ 2020-07-18 23:56  lukelmouse  阅读(53)  评论(0编辑  收藏  举报