洛谷P2040 打开所有的灯 题解 状态压缩枚举

题目链接:https://www.luogu.com.cn/problem/P2040

这道题目是一道比较简单的题目,可以用枚举或者DP做,我这里是用二进制遍历所有的状态,枚举所有的等开或者不开的情况,最后求出代码的。实现代码如下:

#include <bits/stdc++.h>
using namespace std;
int a[3][3], ans = INT_MAX;
int dir[5][2] = { 0, 0, -1, 0, 1, 0, 0, -1, 0, 1 };
void rev(int x, int y) {
    for (int i = 0; i < 5; i ++) {
        int xx = x + dir[i][0], yy = y + dir[i][1];
        if (xx >= 0 && xx < 3 && yy >= 0 && yy < 3) a[xx][yy] = !a[xx][yy];
    }
}
bool check() {
    for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) if (!a[i][j]) return false;
    return true;
}
void rev_all(int st) {
    for (int i = 0; i < 9; i ++) if (st & (1<<i)) rev(i/3, i%3);
    if (check()) ans = min(ans, __builtin_popcount(st));
    for (int i = 0; i < 9; i ++) if (st & (1<<i)) rev(i/3, i%3);
}
int main() {
    for (int i = 0; i < 3; i ++) for (int j = 0; j < 3; j ++) cin >> a[i][j];
    for (int st = 0; st < (1<<9); st ++)
        rev_all(st);
    cout << ans << endl;
    return 0;
}

posted @ 2020-01-16 22:12  quanjun  阅读(160)  评论(0编辑  收藏  举报