码迷,mamicode.com
首页 > 其他好文 > 详细

蓝桥杯历届决赛之分红酒

时间:2015-04-29 15:14:50      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:广度优先搜索   分红酒   蓝桥杯决赛试题   java   bfs   

原题:

有4个红酒瓶子,它们的容量分别是:9升, 7升, 4升, 2升

  开始的状态是 [9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。
  允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。这样的一次 倒酒动作称为1次操作。
  假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?
  本题就是要求你编程实现最小操作次数的计算。
 
  输入:最终状态(逗号分隔)
  输出:最小操作次数(如无法实现,则输出-1)

例如:
输入:
9,0,0,0
应该输出:
0
输入:
6,0,0,3
应该输出:
-1
输入:
7,2,0,0
应该输出:

2


思路:跟我上一篇博客是一样的思路。BFS广度优先搜索。在状态类中由于不需要打印路径,将last值改为存储次数。将瓶子改为4个,容量确定。不懂的可以先去看我上一篇博客。

java code:

package package1;
import java.util.*;
public class T201207_03 {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		
		//确定初始状态
		int[] s = new int[4];
		for(int i = 0;i<s.length;i++)
			s[i] = cin.nextInt();
		Zt start = new Zt(s,0);
		
		//确定结束状态
		int[] ans = new int[4];
		for(int i = 0;i<ans.length;i++)
			ans[i] = cin.nextInt();
		Zt ansZt = new Zt(ans,-1);
		
		//创建队列,初始状态入队
		Queue<Zt> queue = new LinkedList<Zt>();
		queue.add(start);
		
		//声明出队中间变量
		Zt temp = null;
		Zt newZt = null;
		
		int p = 0;
		if(start.equals(ansZt)){
			sop("last = "+start.last);
			return;
		}
		while(!queue.isEmpty())
		{
			//出队
			temp = queue.poll();
			temp.show();
			
			//倒酒,1->2,1->3,1->4
			//	2->1,2->3,2->4
			//      3->1,3->2,3->4
			//<span style="white-space:pre">	</span>4->1,4->2,4->3
			for(int i = 0;i<3;i++)
				for(int j = 0;j<3;j++)
				{
					//相等跳过
					if(i == j)
						continue;
					//产生新的状态
					newZt = temp.move(i,j,temp.last+1);
					//为空则跳过
					if(newZt == null)
						continue;
					queue.add(newZt);
					
					if(newZt.equals(ansZt))
					{
						//newZt.show();
						sop("last = "+newZt.last);
						return;
					}
				}
		}
		sop("-1");
	}
	private static void sop(String string) {
		System.out.println(string);	
	}
}
//状态类
class Zt
{	
		//静态容量
		public static  int[]  rl = {9,7,4,2};
		
		//记录次数
		int last;
		//当前状态
		int[] zt = new int[4];
		
		Zt(int[] pz,int p)
		{
			last = p;
			for(int i = 0;i<zt.length;i++)
				zt[i] = pz[i];
		}
		//判断key值是否存在当前状态
		public int indexOf(int key)
		{
			for(int i = 0;i<zt.length;i++)
			{
				if(zt[i] == key)
					return i;
			}
			return -1;
		}
		
		//将i的酒到入j中
		public Zt move(int i,int j,int p)
		{//比较i瓶的剩余量和j瓶的空闲量
			
			//建立新的状态
			int[] newzt = new int[4];
			for(int k = 0;k<zt.length;k++)
			{
				newzt[k] = zt[k];
			}
			Zt newZt = new Zt(newzt,p);
			//无法倒酒返回null
			if(newZt.zt[i] == 0||newZt.zt[j] == newZt.rl[j])
				return null;
			
			if(newZt.zt[i]<= newZt.rl[j]-newZt.zt[j])
			{//i的酒量小于j的剩余量,i清空,j += i
				newZt.zt[j] += newZt.zt[i];
				newZt.zt[i] = 0;
				return newZt;
			}
			else
			{//i的酒量大于j的剩余量,倒满j后i有剩余
				newZt.zt[i] -= (newZt.rl[j] - newZt.zt[j]);
				newZt.zt[j] = newZt.rl[j];
				return newZt;
			}
		}
		public void show()
		{
			System.out.print("zt = "+this.last+" ");
			for(int i = 0;i<zt.length;i++)
				System.out.print(zt[i]+",");
			sop("");
		}
		
		public boolean equals(Object arg0) {
			Zt e = (Zt)arg0;
			for(int i = 0;i<zt.length;i++){
				if(zt[i]!=e.zt[i])
					return false;
			}
			return true;
		}
		private static void sop(String string) {
			System.out.println(string);
		}
	}


蓝桥杯历届决赛之分红酒

标签:广度优先搜索   分红酒   蓝桥杯决赛试题   java   bfs   

原文地址:http://blog.csdn.net/u013451048/article/details/45365265

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!