很棒的一道题,既锻炼思维,又考验代码能力。在我温故知新结束之后是这样的一道题来迎接我,真的很棒。
思路:
这本质上还是翻转问题,那么也就有一些理所当然的结论:
1、对每个棋子,只有翻转与不翻转的区别
2、翻转的顺序不会影响最终结果
不想证明,偷个懒233~,其实也是一目了然的事
不过和一般的翻转问题相比,它有点棘手,因为它既影响左右,又影响上下,如果只是一条线上的就是通常的翻转问题了,那么自然就想到想办法转换过去,那么,该如何做?
假设当前需要判断第row(row > 1)行,row之前的行都已经操作过了, 那么该翻转哪个其实是固定的了,因为我要通过第row行的操作使上一行的1消失。无解的情况自然就是最后一行在复原了倒数第二行之后,它自己还有剩下的1。
上面的分析其实就是对于每一个固定的第一行所需要进行的操作,那么再将第一行枚举一下不就涵盖了所有的情况了吗~
扫描二维码关注公众号,回复:
1679426 查看本文章
ok,结束
#include <iostream> #include <cstring> using namespace std; const int inf = 0x3f3f3f3f; int g[20][20], rem[20][20], ans[20][20], temp[20][20], vis[20]; int good; int m, n; int ccount = 1; bool ok; void dfs(int row, int cnt){ for(int j = 1; j <= n; j ++){//更新状态 if(rem[row][j] == 1){ g[row][j] = ! g[row][j]; g[row][j - 1] = ! g[row][j - 1]; g[row][j + 1] = ! g[row][j + 1]; g[row - 1][j] = ! g[row - 1][j]; g[row + 1][j] = ! g[row + 1][j]; } } if(row == m){ //判断最后一行是否符合条件 bool flag = false; for(int i = 1; i <= n; i ++){ if(g[row][i] == 1) //最后一行还存在1,则无解 flag = true ; } if(flag == false){ ok = true; if(cnt < good){ good = cnt; for(int i = 1; i <= m; i ++) for(int j = 1; j <= n; j ++) ans[i][j] = rem[i][j]; } if(cnt == good){ //字典序 bool tag = true, flag1 = false; for(int i = 1; i <= m && tag; i ++) for(int j = 1; j <= n && tag; j ++){ if(rem[i][j] < ans[i][j]){ flag1 = true; tag = false; } if(rem[i][j] > ans[i][j]){ tag = false; } } if(flag1){ for(int i = 1; i <= m; i ++) for(int j = 1; j <= n; j ++) ans[i][j] = rem[i][j]; } } } return ; } for(int j = 1; j <= n; j ++){ if(g[row][j] == 1){ rem[row + 1][j] = 1; cnt ++; } } dfs(row + 1, cnt); } void f(int num, int cnt){ if(num == n + 1){ memset(rem, 0, sizeof(rem)); for(int j = 1; j <= n; j ++) rem[1][j] = vis[j]; dfs(1, cnt); for(int i = 1; i <= m; i ++) for(int j = 1; j <= n; j ++) g[i][j] = temp[i][j]; return ; } vis[num] = 1; f(num + 1, cnt + 1); vis[num] = 0; f(num + 1, cnt); } int main(){ cin >> m >> n; ok = false; good = inf; memset(temp, 0, sizeof(temp)); memset(vis, 0, sizeof(vis)); memset(g, 0, sizeof(g)); for(int i = 1; i <= m; i ++) for(int j = 1; j <= n; j ++){ cin >> temp[i][j]; g[i][j] = temp[i][j]; } f(1, 0); if(ok){ for(int i = 1; i <= m; i ++){ for(int j = 1; j < n; j ++){ cout << ans[i][j] << ' '; } cout << ans[i][n] << endl; } } else{ cout << "IMPOSSIBLE" << endl; } return 0; }