POJ 3279 DFS

题意

农夫让牛在田里踩砖块,每一块砖块有黑白两面,每被踩一下,就可以翻一面(白变黑,黑变白),然而牛的脚比较大,每次踩块都会踩到邻近的4块。现在告诉你砖块组成了N*M的图,问奶牛最少踩几下,可以把所有砖块都变白。如果有解一样大的,就选取字典序最小的。

分析

就给出一个N*M的01矩阵,变换规则如题意所示,问最少几次能够形成全0矩阵,并输出方式。如果多个解次数一样,选区字典序最小的。

需要进行枚举,如果我们对第一行的变换状态进行枚举,后面的状态就都能确定。因为当我们变换k行的时候,我们一定要保证,变换完k行后,k-1行一定要是全0的,不然,我们再也无法使k-1行变为0。所以如果确定了第一行的变换,整个图的变换就能够一定确定下来。

枚举第一行变换状态的时候,要求字典序最小,那我们就枚举二进制数一样,0000 , 0001 ,0010 这样枚举第一行。纪录最小答案。

其实可以用for解决,但是写dfs也可以。

代码

 1 /* When all else is lost the future still remains. */
 2 /* You can be the greatest */
 3 #define rep(X,Y,Z) for(int X=(Y);X<(Z);X++)
 4 #define drep(X,Y,Z) for(int X=(Y);X>=(Z);X--)
 5 #define fi first
 6 #define se second
 7 #define mk(X,Y) make_pair((X),(Y))
 8 #define inf 0x3f3f3f3f
 9 #define clr(X,Y) memset(X,Y,sizeof(X))
10 #define pb push_back
11 //head
12 #include <iostream>
13 #include <stdio.h>
14 #include <queue>
15 #include <algorithm>
16 #include <string>
17 #include <map>
18 #include <string.h>
19 using namespace std;
20 #define maxM 20
21 #define maxN 20
22 int dx[] = {0,-1,0,1,0};
23 int dy[] = {0,0,-1,0,1};
24 int ord[maxN][maxM];
25 int cur[maxN][maxM];
26 int re[maxN][maxM];
27 int ansm[maxN][maxM];
28 void flip(int x , int y){
29     rep(i,0,5) cur[x+dx[i]][y+dy[i]] = !cur[x+dx[i]][y+dy[i]];
30 }
31 bool check(int line , int m){
32     rep(i,1,m+1) if(cur[line][i] != 0) return 0;
33     return 1;
34 }
35 bool dfs(int line , int n , int m){
36     if(line == n + 1) return check(line - 1,m);
37     drep(pos,m,1) if(cur[line-1][pos] == 1) {
38         flip(line,pos);
39         re[line][pos] = 1;
40     }
41     if(!check(line - 1,m)) return 0;
42     return dfs(line + 1 , n , m);
43 }
44 bool change(int n , int m){
45     rep(i,2,n+1) rep(j,1,m+1) re[i][j] = 0;
46     rep(i,1,n+1) rep(j,1,m+1) cur[i][j] = ord[i][j];
47     drep(i,m,0){
48         if(i == 0) return 0;
49         if(re[1][i]) continue;
50         else{
51             re[1][i] = 1;
52             rep(j,i+1,m+1) re[1][j] = 0;
53             break;
54         }
55     }
56     rep(i,1,m+1) if(re[1][i]) flip(1,i);
57     return 1;
58 }
59 bool slove(int n , int m){
60     bool ans = 0;
61     int tmin = inf;
62     do{
63         ans = dfs(2,n,m);
64         if(ans){
65             int temp = 0;
66             rep(i,1,n+1) rep(j,1,m+1) temp += re[i][j];
67             if(temp < tmin){
68                 tmin = temp;
69                 rep(i,1,n+1) rep(j,1,m+1) ansm[i][j] = re[i][j];
70             }
71         }
72     }while(change(n,m));
73     return tmin == inf ? 0 : 1;
74 }
75 int main(){
76     int n , m;
77     while(~scanf("%d %d",&n,&m)){
78         rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&ord[i][j]);
79         rep(i,1,n+1) rep(j,1,m+1) cur[i][j] = ord[i][j];
80         clr(re,0);
81         bool ok = slove(n,m);
82         if(ok) rep(i,1,n+1){
83             rep(j,1,m+1){if(j-1) printf(" "); printf("%d",ansm[i][j]);}
84             printf("
");
85         }else printf("IMPOSSIBLE
");
86 
87     }
88     return 0;
89 
90 }
原文地址:https://www.cnblogs.com/ticsmtc/p/5960916.html