题目:
给你一个01矩阵,矩阵大小为M x N。(1 <= M , N <= 15)
每次操作选择一个格子,使得该格子与上下左右四个格子的值翻转。
至少多少次操作可以使得矩阵中所有的值变为0?
请输出翻转方案,若没有方案,输出"IMPOSSIBLE” 。
若有多种方案符合题意,请首先输出翻转次数最少的方案;若方案个数仍不唯一,则输出字典序最小的方案。
输入:
第一行输入两个数:M和N。(1 <= M , N <= 15)
接下来M行,每行N个数,其值只为0或1。
输出:
输出M行,每行N个数。
每个数代表该位置翻转次数
样例:
分析:状态压缩(´A`。) wa得我不省人事
#include<iostream> #include<sstream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<functional> #include<iomanip> #include<numeric> #include<cmath> #include<queue> #include<vector> #include<set> #include<cctype> #define PI acos(-1.0) const int INF = 0x3f3f3f; const int NINF = -INF - 1; typedef long long ll; using namespace std; int m, n; int dx[5] = {0, 1, 0, -1, 0}, dy[5] = {0, 0, 1, 0, -1}; int arr[20][20], temp[20][20], ans[20][20]; int judge(int x, int y) { int sum = arr[x][y]; for (int i = 0; i < 5; ++i) { int nx = x + dx[i], ny = y + dy[i]; if (nx >= 0 && nx < m && ny >= 0 && ny < n) sum += temp[nx][ny]; } return sum % 2; } int cal() { for (int i = 1; i < m; ++i) { for (int j = 0; j < n; ++j) { if (judge(i - 1, j) == 1) temp[i][j] = 1; } } for (int j = 0; j < n; ++j) { if (judge(m - 1, j) == 1) return -1; } int num = 0; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) num += temp[i][j]; } return num; } void func() { int flag = -1; for (int i = 0; i < 1 << n; ++i) { memset(temp, 0, sizeof(temp)); for (int j = 0; j < n; ++j) { temp[0][n - j - 1] = i >> j & 1; } int num = cal(); if (num >= 0 && (flag < 0 || num < flag)) { flag = num; memcpy(ans, temp, sizeof(temp)); } } if (flag < 0) cout << "IMPOSSIBLE" << endl; else { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { cout << ans[i][j]; if (j != n - 1) cout << ' '; } cout << endl; } } } int main() { cin >> m >> n; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) cin >> arr[i][j]; } func(); return 0; }