POJ 3279 Fliptile

//这道题还是很有意思
//最开始无从下手但是 可以发现 翻牌和先后顺序无关 ---> 那么只能翻1次或不翻 因为其他情况和1 0 都是重复的
//那么 如果强行枚举就是2^n
//这里就没有想到了 ------->降维度的简化
//确定第一行后 第二行就要把第一行的1都翻为0 才能继续下去 所以第二行事实是确定的
//以此类推 如果最后一行都为0则成立否则 失败
//那么只需要枚举第一行的情况 1e4的复杂度 很小

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <queue>
  5 #include <string>
  6 #include <algorithm>
  7 #include <set>
  8 #define READ() freopen("in.txt", "r", stdin);
  9 #define WRITE() freopen("out.txt", "w", stdout);
 10 #define INF 0x3f3f3f3f
 11 
 12 using namespace std;
 13 
 14 int M, N;
 15 int maze[28][28], mazecp[28][28];
 16 int perm[28], num = 0;
 17 set<string> s;
 18 int d[4][2] =
 19 {
 20     -1, 0,
 21     0, 1,
 22     1, 0,
 23     0, -1
 24 };
 25 char operation[28][28];
 26 char ans_operation[28][28];
 27 int tmp_ans = 0, ans = INF;
 28 
 29 bool OK(int x, int y)
 30 {
 31     if (x < 0|| x >= M || y < 0 || y >= N) return false;
 32     return true;
 33 }
 34 
 35 
 36 void dfs(int x)//x表示现在在第几列
 37 {
 38     if (x == N)//最后一列已经决定翻完
 39     {
 40         //先把第一行的翻完
 41         tmp_ans = 0;
 42         for (int i = 0; i < N; i++)
 43         {
 44             if (operation[0][i] == '1')
 45             {
 46                 tmp_ans++;
 47                 mazecp[0][i] += 1;
 48                 for (int p = 0; p < 4; p++)
 49                 {
 50                     int nx = 0+d[p][0], ny = i+d[p][1];
 51                     if (OK(nx, ny))
 52                     {
 53                         mazecp[nx][ny] += 1;
 54                     }
 55                 }
 56             }
 57         }
 58         //第一行确定 其余所有行都确定
 59         for (int i = 1; i < M; i++)
 60         {
 61             for (int j = 0; j < N; j++)
 62             {
 63                 if (mazecp[i-1][j] % 2 == 1)
 64                 {
 65                     operation[i][j] = '1';//那么这一个就要翻
 66                     tmp_ans++;
 67                     mazecp[i][j] += 1;
 68                     for (int p = 0; p < 4; p++)//造成的影响
 69                     {
 70                         int nx = i+d[p][0], ny = j+d[p][1];
 71                         if (OK(nx, ny))
 72                         {
 73                             mazecp[nx][ny] += 1;
 74                         }
 75                     }
 76                 }
 77             }
 78         }
 79         //检查最后一行是否为 都为偶数
 80         bool success = true;
 81         for (int i = 0; i < N; i++)
 82         {
 83             if (mazecp[M-1][i] % 2 == 1)
 84             {
 85                 success = false;
 86                 break;
 87             }
 88         }
 89         if (success)
 90         {
 91             if (tmp_ans < ans)//要先保证翻的次数最少 然后是最小字典序 哎 坑了
 92             {
 93                 ans = tmp_ans;
 94                 for (int i = 0; i < M; i++)
 95                 {
 96                     for (int j = 0; j < N; j++) ans_operation[i][j] = operation[i][j];
 97                 }
 98             }
 99             else if (tmp_ans == ans)
100             {
101                 if (strcmp(ans_operation[0], operation[0]) > 0)
102                 {
103                     for (int i = 0; i < M; i++)
104                     for (int j = 0; j < N; j++) ans_operation[i][j] = operation[i][j];
105                 }
106             }//成功
107         }
108         for (int i = 1; i < M; i++) fill(operation[i], operation[i]+N, '0');//重置操作
109         for (int i = 0; i < M; i++)
110         {
111             for (int j = 0; j < N; j++) mazecp[i][j] = maze[i][j];//重置地图
112         }
113         return ;
114     }
115     operation[0][x] = '0';
116     dfs(x+1);
117     operation[0][x] = '1';
118     dfs(x+1);
119     return ;
120 }
121 
122 int main()
123 {
124     //READ()
125     //WRITE()
126     while(~scanf("%d%d", &M, &N))
127     {
128         for (int i = 0; i < M; i++)
129         {
130             for (int j = 0; j < N; j++)
131             {
132                 scanf("%d", &maze[i][j]);
133                 mazecp[i][j] = maze[i][j];
134             }
135         }
136         memset(operation, '0', sizeof(operation));
137         memset(ans_operation, '1', sizeof(ans_operation));
138         ans = INF;
139         dfs(0);
140         if (ans < INF)
141         {
142             for (int i = 0; i < M; i++)
143             {
144                 for (int j = 0; j < N; j++)
145                 {
146                     printf("%c ", ans_operation[i][j]);
147                 }
148                 putchar('
');
149             }
150         }
151         else printf("IMPOSSIBLE
");
152     }
153     return 0;
154 }
原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6516001.html