三個水桶等分8公升水的問題

2022-08-18 19:36:14 字數 4639 閱讀 6070

有三個容積分別為8公升、5公升、3公升的水桶,其中容積為8公升的水桶盛滿了水,容積為5公升和3公升的水桶都是空的。三個水桶都沒有刻度,現在需要將水桶中的8公升水等分成2份,每份都是4公升水。條件是只能使用這三個水桶,不能借助其他工具。

對於這個問題,似乎沒有「規律」可循,沒有專門的演算法來求解,因此只能嘗試使用「窮舉法」來求解。

把每個狀態下三個水桶中的水的體積作為status,例如status = array(8,0,0),想要得到的status = array(4,4,0)。

這樣,就把問題轉化為「尋徑」問題了。只需要找到status = array(8,0,0)轉化到status = array(4,4,0)的「路徑」即可。

對於status有如下限制:

0 <= status[0] <= 8;

0 <= status[1] <= 5;

0 <= status[2] <= 3;

在搜尋sub_status的過程中,要注意sub_status不能和current_status和其祖先相等,要不然程式會進入「環路」。一般的,current_status可以得到好幾個sub_status, 如果sub_status和current_status和其祖先的其中乙個相等,則忽略這個sub_status。

一共有三個水桶,則可能的「倒水」動作共有6種(3中取2的全排列),但是在不同的status下,這6種倒水動作中有一些是不可用:①從某乙個桶中倒水,但是這個桶是空的,②向某乙個桶中倒水,但是這個桶已經滿了。

按照上面的分析,可以構造乙個status類:

status 類有四個protected 字段:

_values 值, 例如array(8,0,0)

_limit 限制, 這裡是array(8,5,3)

_children 用來儲存本物件的所有sub_status的values

_ancestors 用來儲存物件本身的values和祖先的values

程式的大體思路是例項化第乙個status——array(8,0,0),在建構函式中搜尋sub_status、篩選sub_status,然後例項化所有的sub_status,如果sub_status等於array(4,4,0)則停止例項化,並將_ancestors輸出,這樣就可以將所有的「路徑」找出。

物件導向風格

1

<?php2//

path: document-root/obj/status.php34

class

status520

21protected

function

generatechildren()

2231

if($child !== false && !$this->isancestor($child) && $child !== array(4,4,0))

3435

$child = $this->turnstatus($o, $i

);36

if($child === array(4,4,0))

39if($child !== false && !$this->isancestor($child) && $child !== array(4,4,0))42}

43}44$this->_children = $children;45

}4647protected

function isancestor($value)48

53}54return

false;55

}5657protected

function turnstatus($i, $o)58

6364

if($this->_values[$i] == $this->_limit[$i

])67

if(($this->_limit[$i] - $this->_values[$i]) <= $this->_values[$o

])else

7273

$value[$o] -= $m;74

$value[$i] += $m;75

return

$value;76

}7778protected

function showresult(array

$child)79

86 }

1

<?php2//

path: document-root/main.php34

require_once("obj/status.php");

5require_once("register.php");

6echo '';78

$status = new status(array(8, 0, 0), array(8, 5, 3), array

());910

11//

var_dump($status);

1213

$paths = register::registry('final_status');

14printf("共找出 %d 種不同的方式", count($paths

));15

16$stepnum = 0;

17foreach ($paths

as$key => $path

) 21

$_stepnum = count($path

);22

if($_stepnum

< $stepnum)26

}27printf(" 其中,第 %d 種方式所用步數最少,為 %d 步", $_key, $stepnum-1);

28print_r($paths);

1

<?php2//

path: document-root/register.php34

class

register512

13static

public

function register($key, $value)14

1718

static

public)19

2223

static

public

function registry($key)24

28return

null;29

}30 }

將上面貼出來的程式按目錄放在**根目錄下,訪問 main.php 即可得到問題解答。

過程化風格:

1

<?php2//

file: document-root/index.php

3echo '';45

$limit = array(8,5,3);

6$current = array

(7 'value' => array(8,0,0),

8 'ancestors' => array(9

)10);11

$records = array

();12

$tree = getchildren($current, $limit, $records

);13

print_r($records

);14

1516/**

17* @param $current array('value', 'children', 'ancestors')

18* @param array $limit

19* @param array $records

20* @return array

21*/

22function getchildren($current, array

$limit, array &$records)23

3435

$child = turn($o, $i, $pvalue, $limit

);36

if($child !== false && !isancestor($current, $child

))39}40

}4142foreach ($children

as$key => $child

) else56}

57return

$current;58

}5960/**61

* @param $i

62* @param $o

63* @param $value array

64* @param $limit

65* @return bool|array

66*/

67function turn($i, $o, $value, $limit)68

7273

if($value[$i] == $limit[$i

])76

if(($limit[$i] - $value[$i]) <= $value[$o

])else

8182

$value[$o] -= $m;83

$value[$i] += $m;84

return

$value;85

}8687function isancestor(array

$current, array

$child)88

93return

false

;94 }

在瀏覽器中直接訪問這個檔案即可。

三個容器倒水 三個水桶等分8公升水的問題 演算法的樂趣

有三個容積分別為3公升 5公升 8公升的水桶,其中容積為8公升的水桶中裝滿了水,容積為3公升和容積為5公升的水桶都是空的。三個水桶都沒有刻度,現在需要將大水桶中的8公升水等分成兩份,每份都是4公升水,附加條件是只能這三個水桶,不能借助其他輔助容器。恩,是的,這是乙個很經典的問題。然而,我們並不能想全...

第3 2課 用三個水桶等分 8 公升水的問題

有這樣乙個智力題目 有三個分別是 3 公升 5 公升和 8 公升容積的水桶,其中容積為 8 公升的水桶中裝滿了水,容積為 3 公升和容積為 5 公升的水桶是空的,三個水桶都沒有體積刻度。現在需要把大水桶中的 8 公升水等分成兩份,每份都是 4 公升水,附加條件是只能使用這 8 公升水和另外兩個空水桶...

三個桶等分八公升水

狀態樹的遍歷 有這樣一道智力題目 有三個容積分別是3公升 5公升和8公升的水桶,其中容積為8公升的水桶中裝滿了水,容積為3公升和容積為5公升的水桶是空的。3個水桶都沒有體積刻度,現在需要將大水桶中的8公升水等分成兩份,每份都是4公升水,附加條件是只能使用另外兩個空水桶,不能借助其他輔助容器。這是乙個...