poj1753

Flip Game
翻转游戏
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 44910 Accepted: 19247

Description

Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the
在一个4x4的矩阵中放着16块有着两面的圆片。一面是白色一面是黑色,这个片面是水平放置的,因此只会显示一个颜色。
other one is black and each piece is lying either it's black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their 
每一轮你这能翻转3-5块, 因此改变上面的颜色从黑到白,反之亦然。
upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules: 
每一轮如何翻转圆片,请看小下列规则:
  1. Choose any one of the 16 pieces. 在16个片面中任意选择一个
  2. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
  3. 翻转所选块所有相邻块向左,向右,顶部,底部的片面(在该片面四周都可以选择的时候)

Consider the following position as an example: 
考虑下面的位置作为一个例子
bwbw 
wwww 
bbwb 
bwwb 
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. 
这里“b”代表作品躺在黑色的一面,“w”表示碎片躺在白色的一面
If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become: 
如果我们选择翻转从第三行第一块(这个选择是图片所示),然后将成为

bwbw 
bwww 
wwwb 
wwwb 
The goal of the game is to flip either all pieces white side up or all pieces black side up. 
游戏的目标是把所有块翻转成白色一面或块黑色的一面。
You are to write a program that will search for the minimum number of rounds needed to achieve this goal. 
你要编写一个程序,将搜索所需要的最小轮次,实现这一目标。

Input

The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.
4*4字符的输入由“w”或“b”表示,表示游戏领域的位置

Output

Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. 
写入输出文件一个整数——实现目标所需的最小数量的轮的游戏从给定的位置
If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).
如果目标是最初实现,然后写0。 如果它是不可能实现的目标,然后写“不可能”这个词(不含引号)

Sample Input

bwwb
bbwb
bwwb
bwww

Sample Output

4

图片分析


ac代码

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * poj1753
 * 参考:http://blog.csdn.net/hackbuteer1/article/details/7392245
 * 对每一次状态进行二进制压缩(其中b代表1,w代表0)
 * @author liuqiang
 *
 */
public class EnumeTest {

	public static void main(String[] args) {
		readExternalData();
		int end = bfs(start);
		if (end == -1) {
			System.out.println("Impossible");
		} else {
			System.out.println(end);
		}
	}

	/**
	 * 读取外部数据
	 * 每一次状态进行二进制压缩(其中b黑色代表1,w白色代表0)
	 */
	private static void readExternalData() {
		Scanner sc = new Scanner(System.in);
		String[] strs = new String[4];
		for (int i = 0; i < 4; i++) {
			strs[i] = sc.nextLine();
		}
		int state = 0;
		for (int i = 0; i < strs.length; i++) {
			int len = strs[i].length();
			for (int j = 0; j < len; j++) {
				state <<= 1;
				if (strs[i].charAt(j) == 'b') {
					state += 1;
				}
			}
		}
		start = state;
		sc.close();
	}

	/*
	 * visited记录不同状态下的矩阵是否已经出现过
	 * 总共有65536种可能
	 * 这个是为了避免重复翻牌
	 * 也是避免回路
	 * 重复翻牌的情况
	 * 第一种:重复翻一颗棋子
	 * 第二种:当一颗棋子被翻前是一种状态,
	 * 翻过若干次后又回到了该状态,
	 * 那么这个棋子就不能再次被翻,这样会造成回路。
	 * 51200 58368 29184 12544 
	35968 20032 10016 4880 
	2248 1252 626 305 
	140 78 39 19 
	 */
	private static boolean visited[] = new boolean[65536];
	private static int[] flip = new int[] { 51200, 58368, 29184, 12544, 35968, 20032, 10016, 4880, 2248, 1252, 626, 305,
			140, 78, 39, 19 };
	private static int start;

	/**
	 * bfs使用广度优先搜索
	 * 
	 * @param state
	 * @return
	 */
	private static int bfs(int state) {
		/*
		 * 判断输入的是不是全白或者全黑
		 */
		if (state == 0 || state == 0xffff) {
			return 0;
		}
		/*
		 * 队列不同的实现类结果不同
		 * 注意请使用LinkedList,这个是标准的队列实现类,线程不安全
		 * PriorityQueue这个是优先队列,与LinkedList是不同的。
		 * 该状态已经被使用
		 * 进入队列
		 */
		Queue<Node1753> q = new LinkedList<Node1753>();
		Node1753 no = new Node1753(state, 0);
		visited[state] = true;
		q.add(no);
		while (!q.isEmpty()) {
			Node1753 cur = q.poll();
			/*
			 * 选出一个节点,
			 * 16中翻牌方式
			 */
			for (int i = 0; i < 16; i++) {
				int a = cur.state ^ flip[i];
				if (visited[a]) {//去掉重复的
					continue;
				}
				if (a == 0 || a == 0xffff) {
					return cur.step + 1;
				}
				Node1753 n1 = new Node1753(a, cur.step + 1);
				visited[a] = true;
				q.add(n1);
			}
		}
		return -1;
	}

}

/**
 * 翻牌时,不能翻重复的牌(重复翻牌没有意义,浪费翻牌次数)
 * 只是翻牌的循序不同
 */
class Node1753 {
	/*
	 * state表示矩阵状态
	 * step第几次翻转
	 */
	public int state;
	public int step;

	public Node1753() {
	}

	public Node1753(int state, int step) {
		this.state = state;
		this.step = step;
	}

	public String toString() {
		return "Node1753 [state=" + state + ", step=" + step + "]";
	}

}


 

 

 

 























  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值