POJ 3279Fliptile(状态枚举+搜索)
2017-03-12 11:37
302 查看
题目传送门:http://poj.org/problem?id=3279
题意:
给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少
翻转次数将所有棋子反转为黑色的所需翻转的是哪些棋子与次数。
分析:
首先根据题目,每次操作都会影响到周围的“棋子”,而要使得每个1都被反转为0,那么我们就应当每次都反转1下方
的棋子以改变1为0.那么,当我们处理过1到n-1行的时候,前n-1行就都已经是0了,最后我们只需要检查最后一行是
不是全部为0就可以检查这次的出操作是否正确了。如果正确且最小,那就存起来。最后输出,万事大吉。当然,因
为我们要改变第x行的1为0需要反转的是x+1行的位置。而这个整个规则是我们验证一组操作是否能达到目的所用的,
那么我们需要在验证前先确定操作(没操作怎么验证..)。于是根据规则内容可知,只需要能确认第一行的翻转情况,
就能够推出下面所有的翻转情况并验证是否正确。于是需要做的就是枚举第一行的情况了。
题意:
给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少
翻转次数将所有棋子反转为黑色的所需翻转的是哪些棋子与次数。
分析:
首先根据题目,每次操作都会影响到周围的“棋子”,而要使得每个1都被反转为0,那么我们就应当每次都反转1下方
的棋子以改变1为0.那么,当我们处理过1到n-1行的时候,前n-1行就都已经是0了,最后我们只需要检查最后一行是
不是全部为0就可以检查这次的出操作是否正确了。如果正确且最小,那就存起来。最后输出,万事大吉。当然,因
为我们要改变第x行的1为0需要反转的是x+1行的位置。而这个整个规则是我们验证一组操作是否能达到目的所用的,
那么我们需要在验证前先确定操作(没操作怎么验证..)。于是根据规则内容可知,只需要能确认第一行的翻转情况,
就能够推出下面所有的翻转情况并验证是否正确。于是需要做的就是枚举第一行的情况了。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int maxn = 20; int mp[maxn][maxn], flip[maxn][maxn], best[maxn][maxn]; int dir[5][2] = {0, 0, 0, 1, 0, -1, 1, 0, -1, 0}; int n, m; int get(int x, int y)//判断当前情况下是否需要翻转该点下面的位置 { int now = mp[x][y]; for(int i = 0; i <= 4; i++) { int dx = x + dir[i][0]; int dy = y + dir[i][1]; if(dx >= 0 && dx < n && dy >= 0 && dy < m) { now += flip[dx][dy]; } } return now&1; } int work() { for(int i = 1; i < n; i++) for(int j = 0; j < m; j++) if(get(i-1, j)) flip[i][j]++; for(int i = 0; i < m; i++) if(get(n-1, i)) return 0x3f3f3f3f; int cnt = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) cnt += flip[i][j]; return cnt; } int main() { while(cin >> n >> m) { for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) cin >> mp[i][j]; int ans = 0x3f3f3f3f, cnt; for(int i = 0; i < (1<<m); i++) { memset(flip, 0, sizeof(flip)); for(int j = 0; j < m; j++) if(1&(i>>j)) flip[0][j]++; int num = work(); if(num < ans) { ans = num; memcpy(best, flip, sizeof(flip)); } } if(ans == 0x3f3f3f3f) cout << "IMPOSSIBLE\n"; else { for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) printf("%d%c", best[i][j], j == m-1 ? '\n':' '); } } return 0; }
相关文章推荐
- 【POJ 2785 4 Values whose Sum is 0】+ 折半枚举(双项搜索))
- The Pilots Brothers' refrigerator(POJ 2965)(dfs枚举+状态压缩)
- Fliptile POJ - 3279 (状态压缩+枚举) && Flip Game POJ - 1753(状态压缩+bfs暴力)
- poj 1873(枚举所有的状态+凸包)
- poj 2785 4 Values whose Sum is 0(折半枚举(双向搜索))
- 【搜索】POJ-2718 贪心+枚举
- POJ 1166 The Clocks(搜索枚举)
- POJ 1745:Divisibility 枚举某一状态的DP
- The Fortified Forest - POJ 1873(状态枚举+求凸包周长)
- POJ 1753 Flip Game(枚举+状态压缩BFS)
- POJ 1837 Balance (枚举状态的01背包)
- 160_折半枚举(双向搜索) 4 Values whose sum is 0 (POJ No.2785)
- POJ 1321 经典棋盘问题 的搜索和状态压缩解法
- Flip Game(poj1753,状态压缩+暴力枚举)
- POJ 1170 shopping offers 状态压缩 记忆化搜索
- POJ_3279_Fliptile_搜索、二进制枚举
- POJ 1204 Word Puzzles // 字典树,枚举, 搜索
- POJ 1753 Flip Game 状态压缩 枚举
- poj 2965 枚举搜索
- 枚举搜索+贪心:POJ2718--Smallest Difference(解一)