POJ3279 Fliptile题解 二进制枚举搜索法
题目大意:
有一个M*N的方格,1表示黑色,0表示白色,可以翻动方格,每次翻动一个,会将它的上下左右还有自身全部变成相对的颜色,求翻动方格最小次数的方案数。
分析:
可以这样考虑,如果我们确定了第i行的翻动策略,那么如果[i][j]为黑色,则[i+1][j]必须要翻动,否则无法保持最终都为白色,因此我们只要枚举第一行的方案,进而可以逐行确定翻动的方案。因为每一行实质上是一个二进制串,所以我们只要枚举长度为N的二进制串,从0000000...到1111111....即可。最终判断方案是否可行,是通过推导出最后一行方案后检测整个方格是否为白色而确定的。
代码:
1 import java.util.*; 2 import java.io.*; 3 4 public class Main { 5 static final int maxn = 20; 6 static final int dx[] = {-1, 0, 0, 1, 0}; 7 static final int dy[] = {0, 1, 0, 0, -1}; 8 static int n, m, filp[][], opt[][], tile[][]; 9 static InputReader in = new InputReader(System.in); 10 static PrintWriter out = new PrintWriter(System.out); 11 public static int get(int x, int y) { 12 int c = tile[x][y]; 13 for(int i = 0; i < 5; i++) { 14 int tx = x + dx[i]; 15 int ty = y + dy[i]; 16 if(tx >= 0 && tx < n && ty >= 0 && ty < m) { 17 c += filp[tx][ty]; 18 } 19 } 20 return c % 2; 21 } 22 public static int calc() { 23 for(int i = 1; i < n; i++) { 24 for(int j = 0; j < m; j++) { 25 if(get(i - 1, j) != 0) { 26 filp[i][j] = 1; 27 } 28 } 29 } 30 for(int j = 0; j < m; j++) { 31 if(get(n - 1, j) != 0) { 32 return -1; 33 } 34 } 35 int res = 0; 36 for(int i = 0; i < n; i++) { 37 for(int j = 0; j < m; j++) { 38 res += filp[i][j]; 39 } 40 } 41 return res; 42 } 43 public static void solve() { 44 int res = -1; 45 filp = new int[maxn][maxn]; 46 opt = new int[maxn][maxn]; 47 for(int i = 0; i < (1<<m); i++) { 48 for(int k = 0; k < maxn; k++) { 49 for(int j = 0; j < maxn; j++) { 50 filp[k][j] = 0; 51 } 52 } 53 for(int j = 0; j < m; j++) { 54 filp[0][m - j - 1] = i>>j&1; 55 } 56 int num = calc(); 57 if(num >= 0 &&(res < 0 || res > num)) { 58 res = num; 59 for(int k = 0; k < n; k++) { 60 for(int j = 0; j < m; j++) { 61 opt[k][j] = filp[k][j]; 62 } 63 } 64 } 65 } 66 if(res < 0) { 67 out.println("IMPOSSIBLE"); 68 } else { 69 for(int i = 0; i < n; i++) { 70 for(int j = 0; j < m; j++) { 71 out.print(opt[i][j]); 72 if(j < m - 1) { 73 out.print(" "); 74 } 75 } 76 out.print("\n"); 77 } 78 } 79 } 80 public static void main(String[] args) { 81 tile = new int[maxn][maxn]; 82 n = in.nextInt(); 83 m = in.nextInt(); 84 for(int i = 0; i < n; i++) { 85 for(int j = 0; j < m; j++) { 86 tile[i][j] = in.nextInt(); 87 } 88 } 89 solve(); 90 out.close(); 91 } 92 static class InputReader { 93 public BufferedReader reader; 94 public StringTokenizer tokenizer; 95 public InputReader(InputStream stream) { 96 reader = new BufferedReader(new InputStreamReader(stream), 32768); 97 tokenizer = null; 98 } 99 public String next() { 100 try { 101 while(tokenizer == null || !tokenizer.hasMoreTokens()) { 102 tokenizer = new StringTokenizer(reader.readLine()); 103 } 104 } catch (IOException e) { 105 throw new RuntimeException(e); 106 } 107 return tokenizer.nextToken(); 108 } 109 public int nextInt() { 110 return Integer.parseInt(next()); 111 } 112 } 113 }

浙公网安备 33010602011771号