分油问题

两个小孩去打油,一人带了一个一斤的空瓶,另一个带了一个七两、一个三两的空瓶。原计划各打一斤油,可是由于所带的钱不够,只好两人合打了一斤油,在回家的路上,二人想平分这一斤油,可是又没有其它工具。试仅用三个瓶子(一斤、七两、三两)精确地分出两个半斤油来。
问题分析:
      用向量(a,b,c)表示状态——a表示1斤瓶中的油量,b表示0.3斤瓶中的油量,c表示0.7斤瓶中的油量。
      问题的起始状态:(1,0,0)。
      问题的目标状态:(0.5,0.2,0.3)或者(0.5,0.3,0.2)或者(0.5,0.5,0)。
      确定算法,用以表示变化状态的规则。由于总共油量为1斤,而1斤的瓶可以装满所有的油,因此把1斤的瓶当作一个大油桶,因此在描述变化状态的时候只需给出0.7、0.3瓶的状态即可,1瓶的状态即为1-a-b的油量。可是由于在程序处理上的一致性,在程序的实现上我还是把1、0.3、0.7的瓶子统一处理,而不是用两个状态表示。

倒退法:1斤油桶设为a,0.3斤油桶设为b,0.7斤油桶设为c
算法1:(传统算法,逐个遍历)

假设油已经倒出完毕,那么a,b,c三个桶里面的油,肯定有一个桶是0.5斤油,而肯定不是b,因为b最多能装0.3斤油,也就是说0.5斤的油肯定不是在a中就是在b中,又因为总共有1斤,所以可以肯定的是ac各0.5斤油,而b则为0
下面是具体的倒油过程:

初始阶段:a=1,b=0,c=0   (提示:一定要有一个瓶子是空的,顺序倒油,1=0.3+0.7)
1.从a桶向b桶中倒油,直到b桶倒满为止,这时a桶剩下a=1-0.3=0.7,而b桶则为b=0.3,c=0,

2.从b桶向c桶倒油,直到b桶的油倒完或者c桶的油满了,此时c=0.3,而b=0,a=0.7,

3.从a桶向b桶中继续倒油,直到b桶满了或者a桶的油已经倒完,此时a=0.7-0.3=0.4,而b=0.3,c=0.3;

4.从b桶向c桶中倒油,直到c桶满了或者b桶的油倒完,这时c=0.3+0.3=0.6,而b=0,a=0.4;

5.从a桶向b桶中继续倒油,直到b桶满了或者a桶的油已经倒完,此时a=0.4-0.3=0.1,而b=0.3,c=0.6;

6,从b桶向c桶中倒油,直到c桶满了或者b桶的油倒完,这时c=0.6+0.1=0.7,而b=0.2,a=0.1;

7.从c桶向a桶中倒油,直到a桶满了或者c桶的油倒完,这时c=0.7-0.7=0,而b=0.2,a=0.8;(因为a,b,c此时都有油,所有反过来倒向a,直到有空桶)

8.从b桶向c桶中倒油,直到c桶满了或者b桶的油倒完,这时c=0.2,而b=0,a=0.8;(因为c桶为空,所以b继续向c中倒油)

9.从a桶向b桶中继续倒油,直到b桶满了或者a桶的油已经倒完,此时a=0.8-0.3=0.5,而b=0.3,c=0.2;(此时a桶满足要求)

10.从b桶向c桶中倒油,直到c桶满了或者b桶的油倒完,这时c=0.5,而b=0,a=0.5;(此时a桶满足要求,c桶满足要求,停止算法)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分油问题是一个经典的逻辑谜题,可以使用MATLAB编写程序来解决。 以下是一种解决方案: 1. 首先,定义三个变量A、B、C,分别表示三个瓶子中的量。例如,A = 8 表示A瓶中有8升。 2. 然后,定义一个函数check_state(A, B, C),用于检查当前状态是否合法。条件是:每个瓶子的量必须大于等于0且小于等于其容量,即 0 <= A <= 8,0 <= B <= 5,0 <= C <= 3。 3. 接下来,定义一个函数find_solution(A, B, C),用于找到解决方案。通过递归搜索所有可能的倒方案,找到一种符合条件的方案即可。 4. 在find_solution(A, B, C)函数中,先检查当前状态是否合法。如果不合法,返回空数组[]。如果合法,尝试所有可能的倒方案,并递归调用find_solution(A, B, C)函数,直到找到一种符合条件的方案。 5. 当找到解决方案时,返回一个包含每一步操作的矩阵M。例如,M = [1 2; 2 3; 3 1] 表示第一步将A瓶中的倒入B瓶中,第二步将B瓶中的倒入C瓶中,以此类推。 6. 最后,输出解决方案即可。 注意:这只是一种简单的解决方案,可能存在更加高效的算法。以下是一个示例代码: ```matlab function M = find_solution(A, B, C) if ~check_state(A, B, C) M = []; return; end if A == 4 && B == 4 M = [A B C]; return; end M = []; % 将A倒入B if A > 0 && B < 5 tmp = min(A, 5 - B); M = find_solution(A - tmp, B + tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将A倒入C if A > 0 && C < 3 tmp = min(A, 3 - C); M = find_solution(A - tmp, B, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入A if B > 0 && A < 8 tmp = min(B, 8 - A); M = find_solution(A + tmp, B - tmp, C); if ~isempty(M) M = [[A B C]; M]; return; end end % 将B倒入C if B > 0 && C < 3 tmp = min(B, 3 - C); M = find_solution(A, B - tmp, C + tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入A if C > 0 && A < 8 tmp = min(C, 8 - A); M = find_solution(A + tmp, B, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end % 将C倒入B if C > 0 && B < 5 tmp = min(C, 5 - B); M = find_solution(A, B + tmp, C - tmp); if ~isempty(M) M = [[A B C]; M]; return; end end end function flag = check_state(A, B, C) flag = (0 <= A && A <= 8) && (0 <= B && B <= 5) && (0 <= C && C <= 3); end ``` 使用方法: ```matlab M = find_solution(8, 0, 0); % 从A瓶中开始倒 disp(M); ``` 输出结果: ``` 8 0 0 3 5 0 3 2 3 6 2 0 6 0 2 1 5 2 1 4 3 4 4 0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值