标签:
1 /*
2 题意:问最少翻转几次使得棋子都变白,输出翻转的位置
3 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转
4 */
5 #include <cstdio>
6 #include <cstring>
7 #include <algorithm>
8 using namespace std;
9
10 const int MAXN = 20;
11 const int INF = 0x3f3f3f3f;
12 int a[MAXN][MAXN];
13 int b[MAXN][MAXN];
14 int ans[MAXN][MAXN];
15 int dx[5] = {-1, 0, 0, 0, 1};
16 int dy[5] = {0, 1, 0, -1, 0};
17 int n, m;
18
19 int get_col(int x, int y) {
20 int ret = a[x][y];
21 for (int i=0; i<5; ++i) {
22 int tx = x + dx[i], ty = y + dy[i];
23 if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
24 ret += b[tx][ty];
25 }
26 return ret & 1;
27 }
28
29 int check(int s) {
30 memset (b, 0, sizeof (b));
31 for (int i=0; i<m; ++i) {
32 if (s & (1 << i)) b[0][i] = 1;
33 }
34 for (int i=1; i<n; ++i) {
35 for (int j=0; j<m; ++j) {
36 if (get_col (i-1, j)) b[i][j] = 1;
37 }
38 }
39 for (int i=0; i<m; ++i) if (get_col (n-1, i)) return INF;
40 int ret = 0;
41 for (int i=0; i<n; ++i) {
42 for (int j=0; j<m; ++j) ret += b[i][j];
43 }
44 return ret;
45 }
46
47 int main(void) { //POJ 3279 Fliptile
48 while (scanf ("%d%d", &n, &m) == 2) {
49 for (int i=0; i<n; ++i) {
50 for (int j=0; j<m; ++j) {
51 scanf ("%d", &a[i][j]);
52 }
53 }
54 int mn = INF;
55 memset (ans, 0, sizeof (ans));
56 for (int i=0; i<(1<<m); ++i) {
57 int res = check (i);
58 if (res < mn) {
59 mn = res;
60 for (int i=0; i<n; ++i) {
61 for (int j=0; j<m; ++j) {
62 if (b[i][j]) ans[i][j] = 1;
63 else ans[i][j] = 0;
64 }
65 }
66 }
67 }
68 if (mn < INF) {
69 for (int i=0; i<n; ++i) {
70 for (int j=0; j<m; ++j) printf ("%d%c", ans[i][j], (j == m-1) ? ‘\n‘ : ‘ ‘);
71 }
72 }
73 else puts ("IMPOSSIBLE");
74 }
75
76 return 0;
77 }
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4695654.html