POJ - 3279 Fliptile(DFS)

题目大意:给你一个矩阵,要求你将矩阵上的1全部变成0
有一种翻转操作,就是将当前这个位置的数变成另一个数(0变1,1变0),相邻的四个位置的数也要变换
问最后能否将所有的1都变成0,输出变换的最小字典序

解题思路:以一个数为中心的翻转,最多只有1次,因为之后的偶数次相当于没操作,奇数次就和1的效果一样了
所以可以枚举第一行的操作
第一行操作完后,操作其他行,如果要让第一行的1都变成0的话,只能操作第二行,让其变成0了,因为其他行的操作影响不到第一行(除了第一行和第二行),这样,下面的所有行的变化就固定

#include 
#include 
#include 
using namespace std;
const int N = 20;
const int INF = 0x3f3f3f3f;
int num[N], ans[N], state[N];
int Min, n, m;

void init() {
    int t;
    for (int i = 0; i < n; i++) {
        num[i] = 0;
        for (int j = 0; j < m; j++) {
            scanf("%d", &t);
            if (t) num[i] |= (1 << (m - j - 1));
        }
    }
}

void dfs(int cur, int pre, int val) {
    if (cur == n) {
        if (pre == 0) {
            if (val < Min) {
                Min = val;
                for (int i = 0; i < n; i++)
                    ans[i] = state[i];
            }
            else if (val == Min) {
                bool flag = false;
                for (int i = 0; i < n; i++) {
                    if (ans[i] < state[i]) break;
                    else if (ans[i] > state[i]) {
                        flag = true;
                        break;
                    }   
                }
                if (flag) {
                    for (int i = 0; i < n; i++)
                        ans[i] = state[i];
                }
            }
        }
        return ;
    }

    state[cur] = 0;
    int t = num[cur], cnt = 0;
    t ^= state[cur - 1];
    for (int i = 0; i < m; i++) {
        if (pre & (1 << i)) {
            if (i - 1 >= 0) t ^= (1 << (i - 1));
            if (i + 1 < m) t ^= (1 << (i + 1));
            t ^= (1 << i);
            cnt++;
            state[cur] |= (1 << i);
        }
    }
    dfs(cur + 1, t, val + cnt);
}

void solve() {
    Min = INF;
    int All = (1 << m);
    for (int i = 0; i < All; i++) {
        int t = num[0], cnt = 0;
        for (int j = 0; j < m; j++)  {
            if (i & (1 << j)) {
                cnt++;
                t ^= (1 << j);
                if (j + 1 < m) t ^= (1 << (j + 1));
                if (j - 1 >= 0) t ^= (1 << (j - 1));
            }
        }
        state[0] = i;
        dfs(1, t, cnt);
    }

    if (Min != INF) {
        for (int i = 0; i < n; i++) {
            for (int j = m - 1; j >= 0; j--) {
                if (j != m - 1) printf(" ");
                if (ans[i] & (1 << j)) printf("1");
                else printf("0");
            }
            printf("\n");
        }
    }
    else printf("IMPOSSIBLE\n");
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF) {
        init();
        solve();
    }
    return 0;
}

你可能感兴趣的:(ACM-暴力)