Fliptile [POJ3279] [开关问题]

题意

给定一张n*m的方格图,有1,0两种数字,每次可以选取一个十字进行翻转,1变成0,0变成1,问最少需要翻转几次,使它全部变成0,全部如果有重复的,按字典序最小的进行输出;

输入

第一行n,m

下面一个矩阵,代表方格图

输出

按矩阵原格式输出是否需要翻转

Sample Input

4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1

Sample Output

0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0

分析

这道题也是一个开关问题,但是相对于上一题(我博客的上一题[POJ3276]),显然这是个二维的矩阵了,调整一个会对四面八方有影响,这样就不能确定地做一件操作的。我们要想着如何变成一个有固定操作规律的方法。看数据也许能启发我们,因为N只有15,可能跟搜索有关。我们有以往的例子,在列用dfs枚举,在行就可以直接操作/DP。针对这个题,发现如果第一行确定了,第一行的某个值确定了,就只有它正下方的数字影响它,这样就可以确定下一行的翻转情况。以此类推,检验最后一行即可。

代码

 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register int
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll long long
14 #define inf (1<<29)
15 #define maxn 20
16 using namespace std;
17 int n,m,ans=inf;
18 int num[maxn][maxn],gra[maxn][maxn],tag[maxn][maxn],rec[maxn],an[maxn][maxn];
19 inline int read()
20 {
21     int x=0,f=1;char c=getchar();
22     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
23     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
24     return x*f;
25 }
26 
27 inline void modify(int i,int j){gra[i][j]^=1,gra[i-1][j]^=1,gra[i][j-1]^=1,gra[i+1][j]^=1,gra[i][j+1]^=1;}
28 int p;
29 void judge()
30 {
31     memset(tag,0,sizeof(tag));
32     rep(i,1,n)rep(j,1,m)     gra[i][j]=num[i][j];
33     rep(i,1,m)    if(rec[i])    tag[1][i]=1,modify(1,i);
34     rep(i,2,n)
35         rep(j,1,m)
36             if(gra[i-1][j])
37                 modify(i,j),tag[i][j]=1;
38     rep(j,1,m)    if(gra[n][j])    return;
39     int sum=0;
40     rep(i,1,n)rep(j,1,m)    sum+=tag[i][j];
41     if(sum<=ans)    
42     {
43         ans=sum;
44         rep(i,1,n)rep(j,1,m)    an[i][j]=tag[i][j];
45     }
46 }
47 
48 void dfs(int step)
49 {
50     if(step>m){judge();return;}
51     rec[step]=1;dfs(step+1);
52     rec[step]=0;dfs(step+1);
53 }
54 
55 int main()
56 {
57     n=read(),m=read();
58     rep(i,1,n)rep(j,1,m) num[i][j]=read();
59     dfs(1);
60     if(ans==inf)puts("IMPOSSIBLE");
61     else    {rep(i,1,n){rep(j,1,m) printf("%d ",an[i][j]);puts("");}}
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/ibilllee/p/9291356.html