您的位置:首页 > 其它

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

2017-05-22 09:17 260 查看
题目大意:

  有一个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());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: