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 }

 

posted @ 2017-12-20 22:13  wannafly1995  阅读(301)  评论(0)    收藏  举报