题目poj3279
分析此题:
二进制枚举:1 << m 种 情况——对第一行的翻牌情况进行枚举。
每张牌翻一次或不翻,(>=2相当于0,1);
dfs:对行dfs深搜,判断是否满足,满足则返回当前状况的翻牌次数。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define MAXN 16
using namespace std;
int mapn[MAXN][MAXN], change[MAXN][MAXN], out[MAXN][MAXN];
int n, m;
int dir[5][2] = {{0, 0}, {0, 1}, {0, -1}, {1, 0}, {-1, 0}};
inline const int read(){
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9'){ if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
int state(int x, int y){
int sta = mapn[x][y];
for(int i = 0; i < 5; i++){
int x1 = x + dir[i][0];
int y1 = y + dir[i][1];
if(x1 < 1 || x1 > n || y1 < 1 || y1 > m) continue;
sta += change[x1][y1];
}
return sta%2; //%2 是显示现在黑或白
}
int dfs(){
//核心语句
for(int i = 2; i <= n; i++){ //从第二行开始遍历,直到最后一行完成
for(int j = 1; j <= m; j++){ //二维矩阵——两个for循环
if(state(i-1, j)){
change[i][j] = 1;
}
}
}
//判断得结果,dfs()功能————当前枚举的第一行翻牌情况是否能实现,
//若能返回当前的翻牌数
for(int i = 1; i <= m; i++){ //判断最后一行之中:如果有黑子,返回no
if(state(n, i)) return -1;
}
int cnt = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cnt += change[i][j]; //有可能的情况,返回此时情况的翻牌数,便于遍历找到最小情况
return cnt;
}
int main(){
while(cin >> n >> m){
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
mapn[i][j] = read();
int ans = 0x3f3f3f3f;
bool flag = false;
for(int i = 0; i < 1<<m; i++){
memset(change, 0, sizeof(change));
for(int j = 1; j <= m; j++){
change[1][m-j+1] = i>>(j-1) & 1; //枚举,将i代表的01串(一行所有的位置上各个牌翻不翻)逆序填入chang[1][]中
//change[1][j] = i>>(j-1) & 1; //也AC
}
int cont = dfs();
if(cont < ans && cont >= 0){ //cont >= 0必须有,否则cont 返回为-1,被统计上
flag = true;
ans = cont;
/* for(int i = 1; i <= n; i++){ //memcpy(out, change, sizeof(change));
for(int j = 1; j <= m; j++){
out[i][j] = change[i][j];
}
}*/
memcpy(out, change, sizeof(change));
}
}
if(!flag) cout<<"IMPOSSIBLE"<<endl;
else{
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
if(j != 1) cout<<" ";
cout<<out[i][j];
}
cout<<endl;
}
}
}
return 0;
}
疑惑点:
- 第一行逆序,顺序都AC;