翻纸牌游戏_hdu_2209(双向广搜).java

本文介绍了一种有趣的翻纸牌游戏算法问题,目标是最少次数将所有纸牌翻为正面朝上。通过广度优先搜索策略实现,利用状态压缩减少搜索空间,最终给出最优解或不可解的情况。

翻纸牌游戏

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1885    Accepted Submission(s): 661


Problem Description
有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
 

Input
有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
 

Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
 

Sample Input
  
01 011
 

Sample Output
  
NO 1
 

Author
wangye
 

Recommend
wangye   |   We have carefully selected several similar problems for you:   2102  1495  1180  2201  2200 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;


public class Main {//超时
	static String sf="";
	static int len=0;
	//static HashMap<StringBuffer,Integer> map;
	static boolean ok=false;
	public static void main(String[] args) {
		BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
		String s;
		try {
			while((s=bf.readLine())!=null){
				ok=false;
				StringBuffer ss=new StringBuffer(s);
				len=ss.length();
				sf="";
				for(int i=0;i<len;i++)
					sf+="0";
				HashMap<String,Integer> map=new HashMap<String, Integer>();
				map.put(s, 0);
				P p=new P();
				p.s=ss;
				p.num=0;
				Queue<P> q=new LinkedList<P>();
				q.add(p);
				bfs(q,map);
				if(!ok)
					System.out.println("No");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static void bfs(Queue<P> q,HashMap<String,Integer> map) {
		
		while(!q.isEmpty()){
			boolean okk=false;
			if(okk){
				ok=true;
				return;
				
			}
			P d=new P();
			d=q.poll();
			String k=d.s.toString();
			if(k.equals(sf)){
				System.out.println(d.num);
				ok=true;
				return;
			}
			StringBuffer g=d.s;
			for(int i=0;i<len;i++){
				StringBuffer f=new StringBuffer(g);
				if(f.charAt(i)=='0'){
					f.deleteCharAt(i);
					f.insert(i, 1);
				}
				else{
					f.deleteCharAt(i);
					f.insert(i, 0);
				}
				if(i>0){
					if(f.charAt(i-1)=='0'){
						f.deleteCharAt(i-1);
						f.insert(i-1, 1);
					}
					else{
						f.deleteCharAt(i-1);
						f.insert(i-1, 0);
					}
				}
				if(i+1<len){
					if(f.charAt(i+1)=='0'){
						f.deleteCharAt(i+1);
						f.insert(i+1, 1);
					}
					else{
						f.deleteCharAt(i+1);
						f.insert(i+1, 0);
					}
				}
				String f1=f.toString();
				if(map.get(f1)==null){
				//	System.out.println("*****"+f);
				//	System.out.println(map.get(f));
					if(f1.equals(sf)){
						System.out.println(d.num+1);
						okk=true;
						ok=true;
						return;
					}
					P h=new P();
					h.s=f;
					h.num=d.num+1;
					map.put(f1,0);
					q.add(h);
				}
			}
			
			/*if(f.charAt(d.i)=='0'){
				f.deleteCharAt(d.i);
				f.insert(d.i, 1);
			}
			else{
				f.deleteCharAt(d.i);
				f.insert(d.i, 0);
			}
			if(d.i>0){
				if(f.charAt(d.i-1)=='0'){
					f.deleteCharAt(d.i-1);
					f.insert(d.i-1, 1);
				}
				else{
					f.deleteCharAt(d.i-1);
					f.insert(d.i-1, 0);
				}
			}
			if(d.i+1<len){
				if(f.charAt(d.i+1)=='0'){
					f.deleteCharAt(d.i+1);
					f.insert(d.i+1, 1);
				}
				else{
					f.deleteCharAt(d.i+1);
					f.insert(d.i+1, 0);
				}
			}
			if(d.i+1!=len){
				P g=new P();
				g.s=f;
				g.i=d.i+1;
				g.num=d.num+1;
				
			}*/
		}
	}
}

class P{
	StringBuffer s=null;
	int num=0;
}


/*
 * 01543093	2013-11-10 12:19:26	Accepted	1004	5406 MS	26468 KB	Java	zhangyi
 9547285	2013-11-10 14:27:34	Accepted	2209	5593MS	26476K	1594 B	Java	zhangyi
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class Main {//AC
	static char str[] = new char[30];
	static int dis[] = new int[1 << 20], vis[] = new int[1 << 20],
			base[] = new int[20], len, aim;

	public static void main(String[] args) {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		int i;
		aim = 0;
		String s = null;
		try {
			while ((s = bf.readLine()) != null) {
				str = s.toCharArray();
				len = s.length();
				base[0] = 3;
				base[len - 1] = 3 << (len - 2);
				for (i = 1; i < len - 1; i++)
					base[i] = 7 << (i - 1);
				if (len == 1) {
					if (str[0] == '1')
						System.out.println(1);
					else
						System.out.println(0);
					continue;
				}
				int ans = bfs();
				if (ans == -1)
					System.out.println("NO");
				else
					System.out.println(ans);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static int bfs() {
		int i, limit = 1 << len;
		Integer now, next;
		Queue<Integer> q = new LinkedList<Integer>();

		now = 0;
		for (i = len - 1; i >= 0; i--)
			now = now * 2 + str[i] - '0';
		for (i = 0; i < limit; i++)
			vis[i] = 0;
		dis[now] = 0;
		vis[now] = 1;
		q.add(now);

		while (!q.isEmpty()) {
			now = q.poll();
			if (now == aim)
				return dis[aim];
			for (i = 0; i < len; i++) {
				next = now ^ base[i];
				if (vis[next] != 0)
					continue;
				dis[next] = dis[now] + 1;
				vis[next] = 1;
				q.add(next);
			}
		}

		return -1;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值