`

倒水问题

 
阅读更多

原文:http://www.acmerblog.com/pour-water-problem-5615.html

倒水问题

这个题目的版本非常之多,有微软版的,腾讯版的,新浪版的等等,最常见的是给你一个容量为5升的杯子和一个容量为3升的杯子,水不限使用,要求精确得到4升水。问题会有两种形式:

1) 直接以简答的方式给定方案

这个比较简单,即便是不知道什么原理,也可以很快凑出来。假设两个杯子分别为x 5升杯, y  3升杯 :  装满 x  ; x -> y  ;清空Y  ;x -> y  ;装满 x  ;x -> y

解决方案会有多个,写出一个即可。

2) 编程实现

解法也比较多,我首先想到的DFS(深度优先)搜索,每次我们有6种选择,只要不断的尝试下去,总可以搜索完所有的状态,找到一个解。也可以用宽度优先搜索(BFS)。

使用DFS搜索实现的Java代码:

01 /**
02  * @author coder
03  * @copyright www.acmerblog.com
04  */
05 public class PourWater {
06     //所有的6中操作。
07     static String operations[] = {" 装满 x "" 装满 y "," 清空X "" 清空Y "" x -> y "" y -> x "};
08     static Stack<Integer> stack = new Stack<Integer>();
09     static int L1,L2 ;//两个杯子的容量
10     static int target; //目标容量
11     static int len;
12     //防止重复搜索
13     static boolean dp[][] ;
14     public static void dfs(int x,int y){
15         if(dp[x][y]) return;
16         dp[x][y] = true;
17         //找到解决方案
18         if(x == target || y == target){
19             System.out.println("dfs方法 一个倒水方案:");
20             for(int oper:stack)
21                 System.out.println(operations[oper]);
22             return;
23         }
24         stack.push(0);
25         dfs(L1,y);
26         stack.pop();
27  
28         stack.push(1);
29         dfs(x,L2);
30         stack.pop();
31  
32         stack.push(2);
33         dfs(0,y);
34         stack.pop();
35  
36         stack.push(3);
37         dfs(x,0);
38         stack.pop();
39  
40         //x向y倒水
41         stack.push(4);
42         if(x >= (L2-y) )  //x倒不完,还有剩余
43             dfs(x - (L2-y),L2);
44         else
45             dfs(0 ,y + x); //x没有剩余
46         stack.pop();
47  
48         //y向x倒水,需要判断能否倒完
49         stack.push(5);
50         if(y >= (L1-x))
51             dfs(L1,y - (L1-x));
52         else
53             dfs(0,y + x);
54         stack.pop();
55     }
56  
57     public static void main(String[] args) {
58          L1 = 5;
59          L2 = 3;
60         target = 4;
61          len = Math.max(L1, L2) + 1;
62          dp = new boolean[len][len];
63         dfs(0,0);
64     }
65 }

又在网上找到一个穷举法,利用了扩展欧几里得算法(同余定理)的一些概念。

。穷举法实现比较方便,其基本思想是用:用小桶容量的倍数对大桶的容量进行取余。比如3升的桶和5升的桶得到4升水可以这样做:

3 % 5 = 3

6 % 5 = 1

9 % 5 = 4

成功得到4升水。(PS:上面的过程用如何用文字描述了?)

同样,用7升的桶和11升的桶得到2升水可以这样做:

7 % 11 = 7

14 % 11 = 3

21 % 11 = 10

28 % 11 = 6

35 % 11 = 2

成功得到2升水。

哈哈,有了这个基本思想在用笔算答案时简直是遇神杀神,遇佛杀佛,又方便又快速!如果要求用程序来实现如何做了?easy,将倒水问题的基本思想用易于编程的话来翻译下——不断用小桶装水倒入大桶,大桶满了立即清空,每次判断下二个桶中水的容量是否等于指定容量。有了这个倒水问题的编程指导方针后代码非常容易写出:

01 //热门智力题 - 打水问题
02 //基本思想:用小桶容量的倍数对大桶的容量进行取余。
03 //指导方针:不断用小桶装水倒入大桶,大桶满了立即清空,
04 //每次判断下二个桶中水的容量是否等于指定容量。
05 #include<iostream>
06 #include <vector>
07 #include<string>
08 using namespace std;
09 const string OPERATOR_NAME[7] = {
10     "装满A桶","装满B桶",
11     "将A桶清空","将B桶清空",
12     "A桶中水倒入B桶","B桶中水倒入A桶",
13     "成功"
14 };
15 int main()
16 {
17     cout<<"热门智力题 - 打水问题"<<endl;
18     cout<<"  --by MoreWindows( http://blog.csdn.net/MoreWindows )--\n"<<endl;
19  
20     int    a_volume, b_volume, goal_volume;
21     vector<string> record;       //记录操作步数
22     int    ai;
23     int    i, a_water, b_water;
24  
25     cout<<"请输入A桶容量,B桶容量,目标容量:";
26     cin>>a_volume>>b_volume>>goal_volume;
27     a_water = b_water = 0; //A桶,B桶中有多少升水
28     char szTemp[30];
29     while (true)
30     {
31         if (a_water == 0)//A桶没水,就装满水
32         {
33             a_water = a_volume;
34             sprintf(szTemp, "         A:%d  B:%d", a_water, b_water);
35             record.push_back(OPERATOR_NAME[0] + szTemp);//fill A
36         }
37         else
38         {
39             //如果A桶的水比(B桶容量-B桶的水)要多
40             if (a_water > b_volume - b_water)
41             {
42                 //A桶的水==A桶的水+B桶的水-B桶容量
43                 a_water = a_water + b_water- b_volume;
44                 b_water = b_volume;      //B桶的水装满了
45                 sprintf(szTemp, "  A:%d  B:%d", a_water, b_water);
46                 record.push_back(OPERATOR_NAME[4] + szTemp);//A->B  
47                 if (a_water == goal_volume)
48                     break;
49                 b_water = 0;            //将B桶清空
50                 sprintf(szTemp, "       A:%d  B:%d", a_water, b_water);
51                 record.push_back(OPERATOR_NAME[3] + szTemp);
52             }
53             else
54             {
55                 //B桶的水==A桶的水+B桶的水
56                 b_water += a_water;
57                 a_water = 0;
58                 sprintf(szTemp, "  A:%d  B:%d", a_water, b_water);
59                 record.push_back(OPERATOR_NAME[4] + szTemp);//A->B
60                 if (b_water == goal_volume)
61                     break;
62             }
63         }
64     }
65     record.push_back(OPERATOR_NAME[6]); //success
66     cout<<"\n---------------------------------------------------"<<endl;
67     cout<<"一个可行的倒水方案如下"<<endl;
68     vector<string>::iterator pos;
69     for (pos = record.begin(); pos != record.end(); pos++)
70         cout<<*pos<<endl;
71     cout<<"---------------------------------------------------"<<endl;
72     return 0;
73 }

原文:http://www.acmerblog.com/pour-water-problem-5615.html

分享到:
评论

相关推荐

    倒水问题的解答

    从给定文件中我们可以看到,这是一段关于“倒水问题”的C++代码,它涉及到一些编程技巧和算法思路。接下来,我们将从几个方面来详细介绍这个文件中包含的知识点。 ### 标题和描述知识点 #### 倒水问题 - 倒水问题...

    三个容器的倒水问题(C语言实现)

    标题 "三个容器的倒水问题(C语言实现)" 涉及到的是一个经典的算法问题,通常出现在计算机科学的面试或编程挑战中。这个问题的核心是通过使用三个容器来确定如何最大限度地转移水,使得两个容器中的水量之和达到某个...

    分水问题和倒水问题

    分水问题和倒水问题是一种经典的数学和编程挑战,它涉及到如何通过有限的容器和操作,将一定量的水精确地分成目标体积。在这个特定的问题中,我们需要利用一个8升和一个5升的容器,将12升水分为两个6升。这需要巧妙...

    专家系统水壶倒水问题C#程序

    在这个名为“专家系统水壶倒水问题C#程序”的项目中,我们主要关注的是一个经典的逻辑谜题,通常称为“水壶问题”或“倒水问题”。这个问题涉及到两个不同容量的水壶,一个能装4公斤水,另一个能装3公斤水。目标是...

    java项目_五五开倒水

    总的来说,"java项目_五五开倒水"是一个结合了基本编程概念与游戏逻辑的实践项目,对于学习Java和提高问题解决能力很有帮助。通过这个项目,开发者可以锻炼到数据结构的选择、算法设计、用户交互以及错误处理等多...

    comfjshmnp-sec.tar

    两个杯子倒水问题,两个版本解决方案,BFS遍历方式,csdn

    js实现杯子倒水问题自动求解程序

    智力测试题经常遇到类似的逻辑题,给几个容量不等的杯子,让你倒出多少的水。 ...点击这里试试杯子倒水问题自动求解吧 算法基本逻辑: 每个杯子有倒满、倒空、倒入其它杯子的操作,所以总共是: 杯

    Jugs问题求解C++

    这个问题涉及到两个容量分别为m升和k升的水壶,目标是通过倒水操作使得其中一个水壶装满n升水。题目提供的C++代码正是为了解决这个问题。 在C++代码中,首先定义了两个字符数组a和b,分别代表两个水壶,用'A'表示m...

    倒水解密附带源码

    倒水解密是一种趣味性的逻辑推理游戏,通常在数字或者编程领域被用来锻炼思维和问题解决能力。在这款由C#语言实现的倒水解密游戏中,玩家需要通过一系列操作,将不同容量的杯子中的水倒入另一个杯子,使得某个杯子的...

    “倒水”算法代码实现

    "倒水"问题,也被称为水壶问题或液态体积转移问题,是一个经典的计算机科学算法题目,主要涉及数学和逻辑推理。在这个问题中,我们通常有两个或三个有刻度的容器,目标是通过一系列倒水操作,使得某个容器中的水量...

    人工智能 水壶问题的求解.rar

    这个问题通常涉及到两个有固定容量的水壶,以及一个精确度目标,要求通过倒水操作找到一种方法,使得某一个水壶的水位达到特定的目标值。这个问题在计算机科学中具有重要的地位,因为它能够展示如何运用有限的资源和...

    水壶问题(java c++)

    水壶问题,又称“倒水问题”,是一个经典的数学谜题,其基本情景是:有两个不同容量的水壶,一个能装4升水,另一个能装3升水,目标是通过这两个水壶的操作得到特定量的水,例如题目中要求的2升水。此问题需要通过...

    新实验二 人工智能课题之水壶问题.rar

    水壶问题,又称倒水问题或数学谜题,是人工智能领域中常见的逻辑难题。这个问题源自古希腊数学家迪奥芬特的《算术》一书,后来被广泛应用于计算机科学和人工智能的教学中,以演示如何用有限的步骤解决复杂的问题。在...

    几个CSDN高校挑战赛的小例子

    倒水问题是一种经典的容量限制问题,常常出现在算法面试中。例如,有两个容量不同的瓶子,如何通过倒水操作使得其中一个瓶子里恰好装满特定数量的水。这类问题需要运用逻辑推理和递归思维。在编程实现时,可以使用...

    人工智能算法

    水壶问题,又称为“倒水问题”或“计量问题”,是一个古老的智力谜题,最早可追溯到古希腊时期。这个问题通常涉及到两个或多个不同容量的水壶,以及一个目标容量,目标是通过倒水操作使得某个壶中的水量达到目标值。...

    七年级上应用一元一次方程-水箱变高了训练题(有解析北师大版)精选.doc

    倒水问题中计算水面下降的高度等。 此外,还有一些更复杂的问题,如通过剪下的长条面积相等推算原正方形边长;根据座位安排的不同情况建立方程;解决服装订货任务的计划问题;计算火车速度提升前后的差异;以及人力...

    C语言课程设计编程实例

    **水壶问题**:又称倒水问题,要求用两个容量不同的水壶,通过相互倒水来得到特定体积的水。该问题可以通过动态规划或状态转移矩阵的方法解决。关键在于找到所有可行的操作组合,并确定哪种操作序列能导致目标体积。...

    青岛版五四制五年级上册应用题.docx

    14. 水箱倒水问题:水体积不变,求长方体水池水深。 15. 长方体框架问题:根据铁丝长度确定长宽高,计算糊纸面积。 16. 小明行程问题:利用比例关系求全程距离。 17. 康佳公司产量问题:设季度产量为x,建立方程求解...

    75道智力题.doc(大公司笔试)

    1. **水壶倒水问题**:这是一个经典的数学问题,通过反复倒水,找到能够得到3升水的方法。关键在于理解操作过程和利用剩余水量。 2. **杯子移动问题**:这是一道简单的逻辑题,可以通过将前两个装满水的杯子中的一...

Global site tag (gtag.js) - Google Analytics