Jugs

In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with the following puzzle. They were given a 3-gallon jug and a 5-gallon jug and were asked to fill the 5-gallon jug with exactly 4 gallons. This problem generalizes that puzzle.

You have two jugs, A and B, and an infinite supply of water. There are three types of actions that you can use: (1) you can fill a jug, (2) you can empty a jug, and (3) you can pour from one jug to the other. Pouring from one jug to the other stops when the first jug is empty or the second jug is full, whichever comes first. For example, if A has 5 gallons and B has 6 gallons and a capacity of 8, then pouring from A to B leaves B full and 3 gallons in A.

A problem is given by a triple (Ca,Cb,N), where Ca and Cb are the capacities of the jugs A and B, respectively, and N is the goal. A solution is a sequence of steps that leaves exactly N gallons in jug B. The possible steps are

fill A 
fill B 
empty A 
empty B 
pour A B 
pour B A 
success

where "pour A B" means "pour the contents of jug A into jug B", and "success" means that the goal has been accomplished.

You may assume that the input you are given does have a solution.

Input

Input to your program consists of a series of input lines each defining one puzzle. Input for each puzzle is a single line of three positive integers: Ca, Cb, and N. Ca and Cb are the capacities of jugs A and B, and N is the goal. You can assume 0 < Ca <= Cb and N <= Cb <=1000 and that A and B are relatively prime to one another.

Output

Output from your program will consist of a series of instructions from the list of the potential output lines which will result in either of the jugs containing exactly N gallons of water. The last line of output for each puzzle should be the line "success". Output lines start in column 1 and there should be no empty lines nor any trailing spaces.

Sample Input

3 5 4
5 7 3

Sample Output

fill B
pour B A
empty A
pour B A
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
empty B
pour A B
success
题意:有两个容量互质的容器,需要用这两个容器量出目标重量的水,找到其中一组解。
分析:对于每一个状态有六种操作方法:倒满A,倒满B,清空A,清空B,从A倒到B,从B倒到A。可采用广度优先搜索,使得搜索到的解为步数最少的解。
  1 //Problem Name: Jugs
2 //Source: ZOJ 1005
3 //Author: jinjin18
4 //Main idea: BFS
5 //Language: C++
6 //分为六个状态进行BFS,每有一组a,b标志为已搜过,后续出现该分支停止
7 //用于遍历的队列元素需保存其父节点,以便找到时通过递归从头输出步骤
8 //小技巧:可将输出的步骤保存于一个字符串数组便于记录
9 //=======================================================================
10 #include<stdio.h>
11 #include<string.h>
12 #include<map>
13 #define MAXSIZE 100000
14 using namespace std;
15 struct Node{
16 int a,b;
17 int pre; //便于递归逆序输出
18 int state; //保存该步骤的操作
19 }Q[MAXSIZE];
20
21 int last;
22 int p ;
23 int ca,cb,n; //a,b的容量及目标n
24 char outline[6][15] = {"fill A","fill B","empty A","empty B","pour A B","pour B A"};
25 map<int,int> sign; //也可采用sign[1000][1000],但是消耗内存比较大(还是能AC)
26
27
28
29 void output(int x){ //递归实现从头输出
30
31 if(Q[x].pre!=-1){
32 output(Q[x].pre);
33 printf("%s\n",outline[Q[x].state]);
34 }
35 return;
36 }
37 void BFS(int a,int b){
38 if(p > last){ //队列中无元素返回
39 return;
40 }
41 if(a == n||b == n){ //达到目标返回
42 return ;
43 }
44 if(sign[a]!=b+1){ //map中存在该对则不继续搜索该分支,+1操作是为了区分b=0时与无该(a,b)的情况
45 sign[a] = b+1;
46 if(a < ca){ //倒满A
47 Q[++last].a = ca;
48 Q[last].b = b;
49 Q[last].state = 0;
50 Q[last].pre = p;
51 }
52 if(b < cb){ //倒满B
53 Q[++last].a = a;
54 Q[last].b = cb;
55 Q[last].state = 1;
56 Q[last].pre = p;
57 }
58 if(a != 0){ //倒空A
59 Q[++last].a = 0;
60 Q[last].b = b;
61 Q[last].state = 2;
62 Q[last].pre = p;
63 }
64 if(b != 0){ //倒空B
65 Q[++last].a = a;
66 Q[last].b = 0;
67 Q[last].state = 3;
68 Q[last].pre = p;
69 }
70 if(a != 0&& b < cb){ //A倒到B
71 Q[++last].a = a+b-cb > 0?a+b-cb:0;
72 Q[last].b = a+b - Q[last].a;
73 Q[last].state = 4;
74 Q[last].pre = p;
75 }
76 if(b != 0&& a < ca){ //B倒到A
77 Q[++last].b = a+b-ca > 0?a+b-ca:0;
78 Q[last].a = a+b - Q[last].b;
79 Q[last].state = 5;
80 Q[last].pre = p;
81 }
82 }
83 p++;
84 BFS(Q[p].a,Q[p].b); //p++不能以++p的形式写入下标中,不知道为啥
85 return ;
86 }
87
88
89 void init(){
90 sign.clear(); //清空图,其实可以保留sign[0] = 1;
91 return ;
92 }
93
94 int main(){
95 Q[0].pre = -1;
96 while(scanf("%d %d %d",&ca,&cb,&n)!=EOF){
97 //printf("inputOK\n");
98 p = 0;
99 last = 0;
100 init();
101 //printf("here is ok\n");
102 BFS(0,0);
103 //printf("p = %d OK\n",p);
104 //for(int i = 1;i<= p; i++){//
105 //printf("%d %d %d\n",Q[i].pre,Q[i].a,Q[i].b);
106 //}
107 output(p);
108 printf("success\n");
109
110 }
111 return 0;
112 }
收获:通过本题对BFS搜索有了直观认识,第一次使用BFS搜索,体会到了其与DFS的不同之处,一个是队列的思想,一个是堆栈的思想。
 

ZOJ 1005 Jugs(BFS)的更多相关文章

  1. zoj 1649 Rescue (BFS)(转载)

    又是类似骑士拯救公主,不过这个是朋友拯救天使的故事... 不同的是,天使有多个朋友,而骑士一般单枪匹马比较帅~ 求到达天使的最短时间,杀死一个护卫1 units time , 走一个格子 1 unit ...

  2. poj1606 Jugs(BFS)

    题目链接 http://poj.org/problem?id=1606 题意 有两个容量分别为ca,cb的杯子,可以向杯子里倒水,将杯子里的水倒空,将一个杯子里的水倒到另一个杯子里,求怎样倒才能使其中 ...

  3. 深搜(DFS)广搜(BFS)详解

    图的深搜与广搜 一.介绍: p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: justify; orp ...

  4. 【算法导论】图的广度优先搜索遍历(BFS)

    图的存储方法:邻接矩阵.邻接表 例如:有一个图如下所示(该图也作为程序的实例): 则上图用邻接矩阵可以表示为: 用邻接表可以表示如下: 邻接矩阵可以很容易的用二维数组表示,下面主要看看怎样构成邻接表: ...

  5. 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现

    1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...

  6. 【BZOJ5492】[HNOI2019]校园旅行(bfs)

    [HNOI2019]校园旅行(bfs) 题面 洛谷 题解 首先考虑暴力做法怎么做. 把所有可行的二元组全部丢进队列里,每次两个点分别向两侧拓展一个同色点,然后更新可行的情况. 这样子的复杂度是\(O( ...

  7. 深度优先搜索(DFS)和广度优先搜索(BFS)

    深度优先搜索(DFS) 广度优先搜索(BFS) 1.介绍 广度优先搜索(BFS)是图的另一种遍历方式,与DFS相对,是以广度优先进行搜索.简言之就是先访问图的顶点,然后广度优先访问其邻接点,然后再依次 ...

  8. 图的 储存 深度优先(DFS)广度优先(BFS)遍历

    图遍历的概念: 从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph).图的遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础.图的 ...

  9. 数据结构与算法之PHP用邻接表、邻接矩阵实现图的广度优先遍历(BFS)

    一.基本思想 1)从图中的某个顶点V出发访问并记录: 2)依次访问V的所有邻接顶点: 3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,直到图中所有已被访问过的顶点的邻接点都被访问到. 4) ...

随机推荐

  1. JS寄快递地址智能解析

    JS寄快递地址智能解析--2020年7月15日 去年做了些前端内容,最近在整理一些稍微有点用的内容,比如智能解析地址,用户只要输入:张三1351111111江苏省扬州市广陵区XX小区X楼xxx室,就能 ...

  2. 049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句

    049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句 本文知识点:break语句 break语句 break语句前情回顾 1.swi ...

  3. VID和PID

    今天很在一份datasheet上突然看到 VID 和 PID 很奇怪!!还不是很懂!!! 参考:https://blog.csdn.net/gaojinshan/article/details/787 ...

  4. [Docker]linux异常关机,docker镜像丢失

    在运行中的docker容器遇到意外情况,可能会自动终止运行,例如磁盘空间不足. 解决办法: 找到/var/lib/docker/containers文件夹下的所有容器ID 执行命令,查看容器信息 ,找 ...

  5. 关于【s】和[t]字符

    [s]:当一个具有执行权限的文件设置 [s](SetUID) 权限后,用户执行这个文件时将以文件所有者的身份执行.passwd 命令具有 SetUID 权限,所有者为 root(Linux 中的命令默 ...

  6. day39 Pyhton 并发编程02

    一.内容回顾 并发和并行的区别 并发 宏观上是在同时运行的 微观上是一个一个顺序执行 同一时刻只有一个cpu在工作 并行 微观上就是同时执行的 同一时刻不止有一个cpu在工作 什么是进程 一个运行中的 ...

  7. ES异常处理-NoNodeAvailableException

    1.问题描述 ES client客户端能创建,但是在用客户端操作时报:NoNodeAvailableException[None of the configured nodes are availab ...

  8. 【状态压缩DP】HDU 4352 XHXJ'S LIS

    题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...

  9. spring boot:spring security用mysql实现动态权限管理(spring boot 2.3.3)

    一,动态权限管理的优点和缺点 1,优点: 因为控制权限的数据保存在了mysql或其他存储系统中, 可以动态修改权限控制,无需改动代码和重启应用,  权限变更时灵活方便 2,缺点: 权限的设置需要保存在 ...

  10. centos6.8 配置 yum 仓库

    挂载方式 mkdir /mnt/cdrom 加载光盘: mount /dev/cdrom /mnt/cdrom/ 挂载光盘到 /mnt/cdrom/ 挂载成功 cd /etc/yum.repos.d/ ...