POJ3279 Fliptile题解 二进制枚举搜索法

来源:互联网 发布:ae软件苹果版 编辑:程序博客网 时间:2024/06/08 18:59

题目大意:

  有一个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++) {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());}}}

原创粉丝点击