P6201 & P1985 Fliptile S 题解
Fliptile S & 翻转棋 Fliptile S
暴力-47pts
搜索每个格子翻或不翻,最后判断是否每个点都为零即可
点击查看代码
#include <bits/stdc++.h> using namespace std; const int dx[5] = {-1, 0, 0, 1, 0}, dy[5] = {0, -1, 1, 0, 0}; int n, m, a[20][20], ans[400], b[20][20], c[400], ansum; bool f; bool check(){ for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ if (b[i][j]){ return 0; } } } return 1; } void dfs(int x, int y, int t, int sum){ if (sum > ansum){ return ; } if (f && sum == ansum && c[t - 1] > ans[t - 1]){ return ; } if (x == n && y == m + 1){ if (check()){ if (!f || sum < ansum){ for (int i = 1; i < t; i++){ ans[i] = c[i]; } f = 1; return ; } for (int i = 1; i < t; i++){ if (c[i] < ans[i]){ for (int j = 1; j < t; j++){ ans[i] = c[i]; } break; } else if (c[i] > ans[i]){ break; } } } return ; } if (y == m + 1){ dfs(x + 1, 1, t, sum); return ; } for (int i = 0; i < 5; i++){ b[x + dx[i]][y + dy[i]] = !b[x + dx[i]][y + dy[i]]; } c[t] = 1; dfs(x, y + 1, t + 1, sum + 1); for (int i = 0; i < 5; i++){ b[x + dx[i]][y + dy[i]] = !b[x + dx[i]][y + dy[i]]; } c[t] = 0; dfs(x, y + 1, t + 1, sum); } int main() { cin >> n >> m; ansum = n * m + 1; for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ cin >> a[i][j]; b[i][j] = a[i][j]; } } dfs(1, 1, 1, 0); if (!f){ cout << "IMPOSSIBLE"; } else { for (int i = 1; i <= n * m; i++){ cout << ans[i] << ' '; if (i % m == 0){ cout << '\n'; } } } return 0; }
正解-100pts
首先,在字典序最小的情况下,翻的次数只有两种
- 翻奇数次相当于翻
次 - 翻偶数次相当于翻
次
当第一排固定之后,后面翻或不翻都是固定的。
- 当第一排固定后,如果上一行的对应位置为
,那么当前位置 必须 翻一次,依此类推
最后只需判断第
点击查看代码
#include <bits/stdc++.h> using namespace std; const int dx[5] = {-1, 0, 0, 1, 0}, dy[5] = {0, -1, 1, 0, 0}; int n, m, a[20][20], ans[400], b[20][20], leb[20][20], c[400], sum, ansum; bool f; void s(int x, int sum){ if (x == m + 1){ int num = 0, t = m + 1; for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ leb[i][j] = b[i][j]; } } // 之后每行都是固定的 for (int i = 2; i <= n; i++){ for (int j = 1; j <= m; j++){ if (b[i - 1][j]){ num++, c[t] = 1; for (int k = 0; k < 5; k++){ b[i + dx[k]][j + dy[k]] = !b[i + dx[k]][j + dy[k]]; } } else { c[t] = 0; } t++; } } bool flag = 1; for (int i = 1; i <= m; i++){ if (b[n][i]){ // 有内鬼! flag = 0; break; } } if (flag && sum + num < ansum){ // 没有内鬼并且翻的次数少些 f = 1; ansum = sum + num; for (int i = 1; i <= n * m; i++){ ans[i] = c[i]; } } for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ b[i][j] = leb[i][j]; } } return ; } s(x + 1, sum); // 注意!先选不翻的情况才能使字典序最小 // 翻! for (int j = 1; j < 5; j++){ b[1 + dx[j]][x + dy[j]] = !b[1 + dx[j]][x + dy[j]]; } c[x] = 1; s(x + 1, sum + 1); // 回溯 c[x] = 0; for (int j = 1; j < 5; j++){ b[1 + dx[j]][x + dy[j]] = !b[1 + dx[j]][x + dy[j]]; } } int main() { cin >> n >> m; ansum = n * m + 1; for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ cin >> a[i][j]; b[i][j] = a[i][j]; } } s(1, 0); if (!f){ // 不成立 cout << "IMPOSSIBLE"; } else { for (int i = 1; i <= n * m; i++){ cout << ans[i] << ' '; if (i % m == 0){ cout << '\n'; } } } return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17410126.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步