POJ3279 Fliptile题解 二进制枚举搜索法
2017-05-22 09:17
260 查看
题目大意:
有一个M*N的方格,1表示黑色,0表示白色,可以翻动方格,每次翻动一个,会将它的上下左右还有自身全部变成相对的颜色,求翻动方格最小次数的方案数。
分析:
可以这样考虑,如果我们确定了第i行的翻动策略,那么如果[i][j]为黑色,则[i+1][j]必须要翻动,否则无法保持最终都为白色,因此我们只要枚举第一行的方案,进而可以逐行确定翻动的方案。因为每一行实质上是一个二进制串,所以我们只要枚举长度为N的二进制串,从0000000...到1111111....即可。最终判断方案是否可行,是通过推导出最后一行方案后检测整个方格是否为白色而确定的。
代码:
有一个M*N的方格,1表示黑色,0表示白色,可以翻动方格,每次翻动一个,会将它的上下左右还有自身全部变成相对的颜色,求翻动方格最小次数的方案数。
分析:
可以这样考虑,如果我们确定了第i行的翻动策略,那么如果[i][j]为黑色,则[i+1][j]必须要翻动,否则无法保持最终都为白色,因此我们只要枚举第一行的方案,进而可以逐行确定翻动的方案。因为每一行实质上是一个二进制串,所以我们只要枚举长度为N的二进制串,从0000000...到1111111....即可。最终判断方案是否可行,是通过推导出最后一行方案后检测整个方格是否为白色而确定的。
代码:
import java.util.*; import java.io.*; public class Main { static final int maxn = 20; static final int dx[] = {-1, 0, 0, 1, 0}; static final int dy[] = {0, 1, 0, 0, -1}; static int n, m, filp[][], opt[][], tile[][]; static InputReader in = new InputReader(System.in); static PrintWriter out = new PrintWriter(System.out); public static int get(int x, int y) { int c = tile[x][y]; for(int i = 0; i < 5; i++) { int tx = x + dx[i]; int ty = y + dy[i]; if(tx >= 0 && tx < n && ty >= 0 && ty < m) { c += filp[tx][ty]; } } return c % 2; } public static int calc() { for(int i = 1; i < n; i++) { for(int j = 0; j < m; j++) { if(get(i - 1, j) != 0) { filp[i][j] = 1; } } } for(int j = 0; j < m; j++) { if(get(n - 1, j) != 0) { return -1; } } int res = 0; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { res += filp[i][j]; } } return res; } public static void solve() { int res = -1; filp = new int[maxn][maxn]; opt = new int[maxn][maxn]; for(int i = 0; i < (1<<m); i++) { for(int k = 0; k < maxn; k++) { for(int j = 0; j < maxn; j++) { filp[k][j] = 0; } } for(int j = 0; j < m; j++) { 4000 filp[0][m - j - 1] = i>>j&1; } int num = calc(); if(num >= 0 &&(res < 0 || res > num)) { res = num; for(int k = 0; k < n; k++) { for(int j = 0; j < m; j++) { opt[k][j] = filp[k][j]; } } } } if(res < 0) { out.println("IMPOSSIBLE"); } else { for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { out.print(opt[i][j]); if(j < m - 1) { out.print(" "); } } out.print("\n"); } } } public static void main(String[] args) { tile = new int[maxn][maxn]; n = in.nextInt(); m = in.nextInt(); for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { tile[i][j] = in.nextInt(); } } solve(); out.close(); } static class InputReader { public BufferedReader reader; public StringTokenizer tokenizer; public InputReader(InputStream stream) { reader = new BufferedReader(new InputStreamReader(stream), 32768); tokenizer = null; } public String next() { try { while(tokenizer == null || !tokenizer.hasMoreTokens()) { tokenizer = new StringTokenizer(reader.readLine()); } } catch (IOException e) { throw new RuntimeException(e); } return tokenizer.nextToken(); } public int nextInt() { return Integer.parseInt(next()); } } }
相关文章推荐
- POJ_3279_Fliptile_搜索、二进制枚举
- [kuangbin]专题一 简单搜索 D - Fliptile(二进制枚举)
- poj3279 Fliptile【二进制枚举状态】
- [POJ3279]Fliptile(开关问题,枚举)
- C - Fliptile (二进制+搜索)
- POJ 3279 Fliptile(二进制枚举暴力)
- poj3279 Fliptile dfs暴力枚举状态
- POJ - 3279----Fliptile(枚举,遍历)
- 不懂 POJ 3279-Fliptile【搜索】
- POJ 1753 Flip Game 暴力搜索(dfs加枚举)
- POJ 3279 Fliptile(枚举状态)
- poj3279 Fliptile 开关问题
- 【基础练习】【枚举/搜索】codevs1792 分解质因数题解
- POJ 3279 Fliptile (搜索)
- POJ-3279(Fliptile)--简单搜索
- [kuangbin带你飞]专题一 简单搜索D - Fliptile(POJ 3279)
- [kuangbin带你飞]专题一 简单搜索-D - Fliptile POJ - 3279
- POJ 3279 Fliptile 二进制
- POJ 3279 Fliptile(普通搜索)
- POJ3279 Fliptile —— 状态压缩 + 模拟