解题报告 『费解的开关(递推 + 位运算)』

原题地址

这题讲一下第一行的枚举就可以了。

第一行枚举的k的第j位如果是1,是指第一行的这一位应该被切换状态(开或关),与初始状态无关(实际上,遇1切换和遇0切换是一样的)。

那么就直接放代码了。

 

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = (a); i <= (b); i++)

const int inf = 0x3f3f3f3f;

int T;
int dx[5] = {0, 0, 0, -1, 1}, dy[5] = {0, -1, 1, 0, 0};
char lig[10][10];

int MIN(int a, int b) {return a < b ? a : b;}

void turn(int x, int y) {
    rep(i, 0, 4) {
        int a = x + dx[i], b = y + dy[i];
        if (a >= 0 && a <= 4 && b >= 0 && b <= 4)
            lig[a][b] ^= 1;
    }
}

int work() {
    int ans = inf;
    rep(k, 0, (1 << 5) - 1) {
        int res = 0;
        char back_up[10][10];
        memcpy(back_up, lig, sizeof(back_up));
        rep(j, 0, 4) {
            if (k >> j & 1) {
                res++;
                turn(0, j);
            }
        }
        rep(i, 0, 3)
            rep(j, 0, 4)
                if (lig[i][j] == '0') {
                    res++;
                    turn(i + 1, j);
                }
        int flag = 1;
        rep(j, 0, 4)
            if (lig[4][j] == '0') {
                flag = 0;
                break;
            }
        if (flag) ans = MIN(ans, res);
        memcpy(lig, back_up, sizeof(lig));
    }
    if (ans > 6) return -1;
    return ans;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    cin >> T;
    while (T--) {
        rep(i, 0, 4)
            rep(j, 0, 4)
                cin >> lig[i][j];    
        cout << work() << endl;
    }
    return 0;
}
View Code
posted @ 2019-07-16 22:08  雲裏霧裏沙  阅读(180)  评论(0编辑  收藏  举报