小孩分油問(wèn)題 (附python代碼)

小孩分油問(wèn)題

題目:

兩個(gè)小孩去打油齿尽,一個(gè)人帶了一個(gè)一斤的空瓶沽损,另一個(gè)帶了一個(gè)七兩、一個(gè)三兩的空瓶循头。原計(jì)劃各打一斤油绵估,可是由于所帶的錢(qián)不夠,只好兩人合打了一斤油卡骂,在回家的路上国裳,兩人想平分這一斤油,可是又沒(méi)有其它工具全跨,試僅用三個(gè)瓶子(一斤缝左、七兩、三兩)精確地分成兩個(gè)半斤油來(lái)浓若。

算法設(shè)計(jì)

設(shè)置三個(gè)油瓶分別為A, B, C渺杉,初始化三個(gè)油瓶的初始狀態(tài)(10,0,0),滿(mǎn)油狀態(tài)(10,7,3)挪钓,目標(biāo)狀態(tài)(5,5,0)是越。使用廣度優(yōu)先的搜索方法,對(duì)每一種可能情況進(jìn)行遍歷碌上,最終取得結(jié)果倚评。其中浦徊,對(duì)于每一種情況對(duì)應(yīng)每一步操作,操作需要滿(mǎn)足一定的約束條件:把A瓶中的油全部倒入B瓶或者把A瓶中的油部分倒入B瓶使B瓶滿(mǎn)油天梧。具體的約束條件見(jiàn)程序流程盔性。本算法由python實(shí)現(xiàn)。

程序流程

1.png
序號(hào) 規(guī)則 解釋
1 (B,C) and B<7 -> (7,C) B瓶不滿(mǎn)的時(shí)候裝滿(mǎn)
2 (B,C) and C<3 -> (B,3) C瓶不滿(mǎn)的時(shí)候裝滿(mǎn)
3 (B,C) and B>0 -> (0,C) B瓶不滿(mǎn)的時(shí)候裝滿(mǎn)
4 (B,C) and C>0 -> (B,0) C瓶不滿(mǎn)的時(shí)候裝滿(mǎn)
5 (B,C) and B>0 and B+C<=3 -> (0,B+C) B瓶的油全倒入C瓶
6 (B,C) and C>0 and B+C<=7 -> (B+C,0) C瓶的油全倒入B瓶
7 (B,C) and B>0 and B+C>=3 -> (B+C-3,3) B瓶的油全倒入C瓶
8 (B,C) and C>0 and B+C>=7 -> (7,B+C-7) C瓶的油全倒入B瓶
1.png

核心偽代碼

Def 下一步:
下一個(gè)操作 = [
        (倒出瓶標(biāo)簽, 倒入瓶標(biāo)簽)
        for 倒出瓶標(biāo)簽 range(3) for 倒入瓶標(biāo)簽 in range(3)
if 倒入/出瓶標(biāo)簽不能相同 and 倒出的瓶不為空 and 已經(jīng)滿(mǎn)了的瓶不能再倒入    ]

    for 倒出瓶標(biāo)簽, 倒入瓶標(biāo)簽 in 下一步操作:
        if 倒出倒入瓶由量之后不超過(guò)倒入瓶最大容量
            倒出瓶油量 -= (倒入瓶最大容量-倒入瓶現(xiàn)有油量)
            倒入瓶油量 = 倒入瓶最大容量
        else:
            倒出瓶油量 = 0
            倒入瓶油量 = 倒入瓶現(xiàn)有油量 + 倒出瓶現(xiàn)有油量
        yield 下一步

Def 搜索結(jié)果:
for 操作in 下一步:
        if 沒(méi)有試過(guò)該操作:
            將該操作加入隊(duì)列
            if 當(dāng)前結(jié)果== 目標(biāo)結(jié)果:
              輸出結(jié)果
            else:
                遞歸本函數(shù)‘搜索結(jié)果’
            刪除隊(duì)列最后一個(gè)

代碼運(yùn)行及測(cè)試:

·.png

結(jié)論

由代碼運(yùn)行結(jié)果可知:整棵樹(shù)一共有20種方法能夠達(dá)到要求腿倚,其中最佳即路徑最短的方法為第9種方法纯出。

第9種方法:[10, 0, 0]->[3, 7, 0]->[3, 4, 3]->[6, 4, 0]->[6, 1, 3]->[9, 1, 0]->[9, 0, 1]->[2, 7, 1]->[2, 5, 3]->[5, 5, 0]

具體做法為:

? 0) 初始化-->[10, 0, 0]
? 1) A瓶倒?jié)MB瓶-->[3, 7, 0]
? 2) B瓶倒?jié)MC瓶-->[3, 4, 3]
? 3) C瓶倒?jié)MA瓶-->[6, 4, 0]
? 4) B瓶倒?jié)MC瓶-->[6, 1, 3]
? 5) C瓶倒?jié)MA瓶-->[9, 1, 0]
? 6) B瓶倒?jié)MC瓶-->[9, 0, 1]
? 7) A瓶倒?jié)MB瓶-->[2, 7, 1]
? 8) B瓶倒?jié)MC瓶-->[2, 5, 3]
? 9) C瓶倒?jié)MA瓶-->[5, 5, 0]

源代碼:

'''
@author: 嘿芝麻

@software: garner
@file: main_oil.py
@time: 2018/10/5
'''
from collections import deque

def nextStep(current_state, oil_volume):
    next_action = [
        (from_, to_)
        for from_ in range(3) for to_ in range(3)
        if from_ != to_ and current_state[from_] > 0 and current_state[to_] < oil_volume[to_]
    ]

    for from_, to_ in next_action:
        next_state = list(current_state)
        if current_state[from_] + current_state[to_] > oil_volume[to_]:
            next_state[from_] -= (oil_volume[to_] - current_state[to_])
            next_state[to_] = oil_volume[to_]
        else:
            next_state[from_] = 0
            next_state[to_] = current_state[to_] + current_state[from_]
        yield next_state


def searchResult(record, oil_volume=[10, 7, 3], final_state=[5, 5, 0]):
    global num, record_list
    current_state = record[-1]
    next_stage = nextStep(current_state, oil_volume)

    for stage in next_stage:
        if stage not in record:
            record.append(stage)
            if stage == final_state:
                numm = num + 1
                s_numm = str(numm)
                str_record = ''
                for i in record:
                    str_record += str(i)
                    if i != [5, 5, 0]:
                        str_record += '->'
                print("方法{}:{}".format(s_numm, str_record))
                record_list.append(deque(record))
                num += 1
            else:
                searchResult(record, oil_volume, final_state)
            record.pop()


if __name__ == '__main__':
    initial_oil_state = [10, 0, 0]
    oil_volume = [10, 7, 3]
    num = 0
    record_list = []
    record = deque()
    record.append(initial_oil_state)
    searchResult(record)
    number = "廣度優(yōu)先搜索共有{}種方法".format(num)
    shortest = "路徑最短的方法中操作步總數(shù)為{}".format(min([len(i) for i in record_list]))

    print(number)
    print(shortest)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市敷燎,隨后出現(xiàn)的幾起案子暂筝,更是在濱河造成了極大的恐慌,老刑警劉巖硬贯,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焕襟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饭豹,警方通過(guò)查閱死者的電腦和手機(jī)鸵赖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拄衰,“玉大人它褪,你說(shuō)我怎么就攤上這事∏滔ぃ” “怎么了茫打?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)妖混。 經(jīng)常有香客問(wèn)我老赤,道長(zhǎng),這世上最難降的妖魔是什么制市? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任抬旺,我火速辦了婚禮,結(jié)果婚禮上祥楣,老公的妹妹穿的比我還像新娘开财。我一直安慰自己,他們只是感情好荣堰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布床未。 她就那樣靜靜地躺著,像睡著了一般振坚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斋扰,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天渡八,我揣著相機(jī)與錄音啃洋,去河邊找鬼。 笑死屎鳍,一個(gè)胖子當(dāng)著我的面吹牛宏娄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逮壁,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孵坚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窥淆?” 一聲冷哼從身側(cè)響起卖宠,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忧饭,沒(méi)想到半個(gè)月后扛伍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡词裤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年刺洒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吼砂。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逆航,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渔肩,到底是詐尸還是另有隱情因俐,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布赖瞒,位于F島的核電站女揭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏栏饮。R本人自食惡果不足惜吧兔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望袍嬉。 院中可真熱鬧境蔼,春花似錦、人聲如沸伺通。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)罐监。三九已至吴藻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弓柱,已是汗流浹背沟堡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工侧但, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人航罗。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓禀横,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親粥血。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柏锄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354