1.問題描述
兩個小孩去打油,一人帶了乙個一斤的空瓶,另乙個帶了乙個七兩、乙個三兩的空瓶。原計畫各打一斤油,可是由於所帶的錢不夠,只好兩人合打了一斤油,在回家的路上,兩人想平分這一斤油,可是又沒有其它工具,試僅用三個瓶子(一斤、七兩、三兩)精確地分成兩個半斤油來。
2.演算法設計
假設狀態a(x1,x2,x3)表示依次表示一斤,七兩,三兩瓶子中含油量為x1,x2,x3
每乙個瓶子含油量為0則不變。如果含油量不為0則可以選擇向其他兩個瓶子倒油,倒油的情況又可以分為兩種:1.當前瓶子剩餘油量不夠倒滿其他某個瓶子;2.當前瓶子剩餘油量足夠倒滿其他的某個瓶子
3.程式流程
1.將初始狀態s(10,0,0)加入到佇列之中。
2.從佇列中取出隊首元素對應的狀態a,狀態a進行寬度優先搜尋,狀態a擴充得到的狀態b,如果狀態b即為目標狀態(5,5,0)側退出搜尋,轉到步驟5。
3.判斷狀態b是否在佇列中,不在的話就新增至佇列末尾,並且記錄下狀態b的前乙個狀態為狀態a,方便找到目標狀態之後尋找解的路徑。已經在佇列中的話側跳過
4.用狀態a搜尋完所有的下乙個狀態之後,狀態a出隊,判斷佇列是否為空,為空的話就停止搜尋,宣告搜尋失敗;佇列不為空的話就轉到步驟2
5.搜尋過程中記錄了每個狀態的前乙個狀態,所以可以利用目標狀態輸出整個搜尋路徑。
4.**實現
import copy
class path(object):
def __init__(self, p, pre=-1):
self.p = p #當前狀態
self.pre = pre #前一步
def pour(i, j, p): #倒油處理
if p[i] >= (cap[j]-p[j]): #當前瓶子剩餘油量足夠倒滿其他的某個瓶子
p[i] = p[i]-(cap[j]-p[j])
p[j] = cap[j]
else: #當前瓶子剩餘油量不夠倒滿其他某個瓶子
p[j] += p[i]
p[i] = 0
def bfs(start, que):
front, tail = 0, 0
que[tail] = start
# que[tail].p = start.p
# que[tail].pre = start.pre
tail += 1
book[start.p[0]*100 + start.p[1]*10 + start.p[2]] = 1 #避免出現重複的狀態
while front <= tail:
node = que[front]
for i in range(0, 3):
if node.p[i] != 0:
for j in range(1, 3):
temp = copy.deepcopy(node.p)
pour(i, (i+j)%3, temp)
if (temp[0]==5 and temp[1]==5):
que[tail].p = temp
que[tail].pre = front
output(que[tail])
print("")
# return tail
if book[temp[0] * 100 + temp[1]*10 + temp[2]]:
continue
book[temp[0] * 100 + temp[1]*10 + temp[2]] = 1
que[tail].p = temp
que[tail].pre = front
tail += 1
front += 1
def output(node):
if node.pre == -1:
print(node.p)
return
output(que[node.pre])
print(node.p)
start = path([10, 0, 0], -1)
cap = [10, 7, 3]
que = [path(none) for i in range(100)] #假設最多一百步
book = [0]*100000
end = bfs(start, que)
# output(que[end])
6.結論油瓶分油問題借助廣度優先搜尋樹可以得到較好的解決。只要問題有解,廣度優先搜尋一定能在有限步內找到解且路徑最短。但是隨著深度的增加,結點數目指數增長,導致組合**。導致空間占用**。最後是可以利用啟發式搜尋效率會更高一些。 程式碎片 分油問題 bfs
這個問題是看演算法精華版時候看見的,人家的演算法看了很頭大,自己寫一遍後覺得清楚多了 using system using system.collections.generic using system.linq using system.text using system.windows.form...
三個油瓶分油問題
原問題 兩個小孩去打油,乙個人帶了乙個一斤的空瓶,另乙個帶了乙個七兩乙個三兩的空瓶。原計畫各打一斤油,可是由於所帶的錢不夠,只好兩人合打了一斤油,可是又沒有其它工具,試僅用三個瓶子 一斤 七兩 三兩 精確地分成兩個半斤油來。a.將分油問題構造的多叉樹存入佇列oilqueue 中,盡量將在陣列 arr...
小孩報數問題
description 有n個小孩圍成一圈,給他們從1開始依次編號,現指定從第w個開始報數,報到第s個時,該小孩出列,然後從下乙個小孩開始報數,仍是報到s個出列,如此重複下去,直到所有的小孩都出列 總人數不足s個時將迴圈報數 求小孩出列的順序。input 第一行輸入小孩的人數n n 64 接下來每行...