题目:
https://vjudge.net/problem/POJ-3279
参考的题解:
POJ-3279 经典翻转问题_越努力越幸运—liupu-CSDN博客
翻转吧!POJ 3279! - 知乎 (zhihu.com)
思路:
把第一排的01串给枚举出来(直接按照字典序来)
从第二排开始把每种情况用b存下来
检查每种情况最后一排有没有黑色
如果全白从第一排开始把总的翻转次数算出来
#include<cstdio> #include<string.h> int a[20][20]; int b[20][20]; int c[20][20]; int n,m; const int inf=0x3f3f3f3f; int d[5][2]={{1,0},{0,1},{-1,0},{0,-1},{0,0}}; int get(int x,int y) { int res=a[x][y]; for(int i=0;i<5;i++) { int fx=x+d[i][0]; int fy=y+d[i][1]; if(fx>=1&&fx<=n&&fy>=1&&fy<=m) { res+=b[fx][fy]; } } return res%2; } int slove() { int ans=0; for(int i=2;i<=n;i++) { for(int j=1;j<=m;j++) { if(get(i-1,j)) b[i][j]=1; } } //检查最后一排 for(int j=1;j<=m;j++) { if(get(n,j)) return inf; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) ans+=b[i][j]; } return ans; } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); } int fi=inf; for(int s=0;s<(1<<m);s++) { memset(b,0,sizeof(b)); for(int j=1;j<=m;j++) { b[1][j]=(s>>(m-j))&1; } int te=slove(); if(te<fi) { fi=te; memcpy(c,b,sizeof(b)); } } if(fi==inf) printf("IMPOSSIBLE\n"); else { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { printf("%d ",c[i][j]); } printf("\n"); } } }