蓝桥杯决赛试题之分酒(BFS)

原题如下:

使得某个容器中正好有6升油。

下面的列表是可能的操作状态记录:

12,0,0

4,8,0

4,3,5

9,3,0

9,0,3

1,8,3

1,6,5

每行3个数据,分别表示12,8,6升容器中的油量

第一行表示初始状态,第二行表示把12升倒入8升容器后的状态,

第三行是8升倒入5升,…

当然,同一个题目可能有多种不同的正确操作步骤。

本题目的要求是,请你编写程序,由用户输入:各个容器的容量,

有可能实现,则输出:“不可能”。

例如,用户输入:

12,8,5,12,0,0,6

得到的油量(放在哪个容器里得到都可以)

则程序可以输出(答案不唯一,只验证操作可行性):

12,0,04,8,04,3,59,3,09,0,31,8,31,6,5

每一行表示一个操作过程中的油量状态。

思路:标准的BFS(广度优先搜索),模拟倒酒将每一个状态入队,然后遍历队。注释很详细,不懂的可以看注释。

java code:

<span style="font-size:18px;">package package1;import java.util.*;/*利用队列模拟倒酒 * */public class T201207_2 {List<Zt> ans = null;public static void main(String[] args) {Scanner cin = new Scanner(System.in);//确定容量int[] rl = new int[3];for(int i = 0;i<rl.length;i++){rl[i] = cin.nextInt();}Zt.rl = rl;//确定初始状态int[] pz = new int[3];for(int i = 0;i<rl.length;i++){pz[i] = cin.nextInt();}//确定key值int key = cin.nextInt();//创建队列,初始状态入队Zt zt = new Zt(pz,-1);List<Zt> queue = new ArrayList<Zt>();queue.add(zt);//声明出队中间变量Zt temp = null;Zt newZt = null;int p = 0;while(!queue.isEmpty()){//出队temp = queue.get(p++);//temp.show();//倒酒, 1->2,1->3//2->1,2->3//3->1,3->2for(int i = 0;i<3;i++)for(int j = 0;j<3;j++){//相等跳过if(i == j)continue;//产生新的状态newZt = temp.move(i,j,p-1);//为空则跳过if(newZt == null)continue;//新状态入队queue.add(newZt);//判断是否得到结果if(newZt.indexOf(key)!= -1){//newZt.show();show(queue,p);return;}}}</span><span style="font-size:18px;"><span style="white-space:pre"></span>System.out.println("不可能");}//路径打印函数private static void show(List<Zt> queue, int p) {//list存储路径List<Zt> list = new ArrayList<Zt>();//最终结果进入listZt zt = queue.get(queue.size()-1);list.add(zt);//依次将结果存入listwhile(zt.last!=-1){zt = queue.get(zt.last);list.add(zt);}//逆序打印for(int i = list.size()-1;i>=0;i–){list.get(i).show();}}}//状态类class Zt{//静态容量public static int[] rl;//上一状态的ipint last;//当前状态int[] zt = new int[3];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[3];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(){sop("zt = "+this.last+" ");for(int i = 0;i<zt.length;i++)System.out.print(zt[i]+",");sop("");}private static void sop(String string) {System.out.println(string);}}</span>还有一道蓝桥杯的题叫分红酒也是BFS的。见我下一篇博客,思路是一样的,,只不过在输出时少有改动。

人之所以有一张嘴,而有两只耳朵,原因是听的要比说的多一倍。

蓝桥杯决赛试题之分酒(BFS)

相关文章:

你感兴趣的文章:

标签云: