蓝桥杯历届决赛之分红酒

来源:互联网 发布:王欣老婆捐钱知乎 编辑:程序博客网 时间:2024/04/29 09:55

原题:

有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->3for(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);//无法倒酒返回nullif(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 += inewZt.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);}}


0 0
原创粉丝点击