Fliptile POJ - 3279(状态压缩)

题意:给你一个n * m的矩阵,元素为0/1, 求把所有的元素变成0所需要的最少操作。(每对一个格子操作,该十字格的元素反转)

分析:一看数据量 <= 15, 就有点状态压缩的感jio。从小到大枚举第一行的操作,因为第一行的操作决定了后面所有的操作,所以最后判断对于第一行的操作是不是符合题意即可。

代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 using namespace std;
 6 const int maxn = 20;
 7 int now;
 8 int g[maxn][maxn];
 9 int cnt[maxn][maxn];
10 int res[(1 << 15) + 10][maxn][maxn];
11 
12 int main()
13 {
14     int n, m; cin >> n >> m;
15     for (int i = 1; i <= n; i++)
16         for (int j = 1; j <= m; j++)
17             cin >> g[i][j];
18     int minn = 1e9;
19     for (now = 0; now < (1 << m); now++)
20     {
21         int tmp = now;
22         int ope = 0;
23         memset(cnt, 0, sizeof(cnt));
24         for (int i = m; i >= 1; i--)
25         {
26             if (tmp & 1)
27             {
28                 ope++;
29                 cnt[1][i]++, cnt[2][i]++;
30                 if (i >= 2) cnt[1][i - 1]++;
31                 if (i <= m - 1) cnt[1][i + 1]++;
32                 res[now][1][i]++;
33             }
34             tmp >>= 1;
35         }
36         for(int i = 2; i <= n; i++)
37             for (int j = 1; j <= m; j++)
38             {
39                 if ((g[i - 1][j] + cnt[i - 1][j]) & 1)
40                 {
41                     ope++;
42                     cnt[i][j]++, cnt[i - 1][j]++, cnt[i + 1][j]++;
43                     if (j >= 2) cnt[i][j - 1]++;
44                     if (j <= m - 1) cnt[i][j + 1]++;
45                     res[now][i][j]++;
46                 }
47             }
48         int flag = 0;
49         for(int i = 1; i <= m; i++)
50             if ((g[n][i] + cnt[n][i]) & 1)
51             {
52                 flag = 1;
53                 break;
54             }
55         if (!flag)
56             res[now][0][0] = ope, minn = min(minn, ope);
57         else res[now][0][0] = -1;
58     }
59     for(int i = 0; i < (1 << 15); i++)
60         if (res[i][0][0] == minn)
61         {
62             for (int j = 1; j <= n; j++)
63                 for (int k = 1; k <= m; k++)
64                     printf("%d%c", res[i][j][k], k == m ? '\n' : ' ');
65             return 0;
66         }
67     printf("IMPOSSIBLE");
68 }

 

posted @ 2019-10-13 12:18  滚烫的青春  阅读(129)  评论(0编辑  收藏  举报