問題重述:
description
喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計乙個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。
input
輸入包含多組資料,每組資料報括兩行。第一行是乙個不超過64的整數,表示砍斷之後共有多少節木棍。第二行是截斷以後,所得到的各節木棍的長度。在最後一組資料之後,是乙個零。
output
為每組資料,分別輸出原始木棒的可能最小長度,每組資料佔一行。
sample input
95 2 1 5 2 1 5 2 1
41 2 3 4
0sample output65
解題思路: 搜尋+列舉+遞迴
[cpp]view plain
copy
/** poj 1011 sticks problem **/
//totalsticks 木棒的總數
//len 正在嘗試的原始木棍長度
//unusedsticks 尚未拼接到len中的木棍
//temp 當前正在拼接的木棍的剩餘長度
#include
#include
bool is_original(int,int,int,int); //遞迴函式,判斷某一長度是否可能是木棒的原始長度
int cmp(const void *elem1,const void *elem2) //qsort比較函式
int sticks[100]; //存放木棍的陣列
bool used[100]; //記錄木棍的使用情況
int main()
qsort(sticks,n,sizeof(int),cmp); //對木棍進行排序
len = sticks[0]; //len的最小可能就是 最長的那一條木棍
for(i=len; i<=sum; i++) //按公升序列舉原始木棒的可能長度
} scanf("%d",&n);
} return 0;
} bool is_original(int totalsticks,int unusedsticks,int temp,int len)
return false;
} 這個回溯的剪枝實在是太精妙了,只有一句話,但是確實很難想到。這篇部落格的**我覺得是風格最優雅的乙個了,就是裡面的原理講的不是太清楚,在這裡記一下。
if(sticks[i]==temp||temp==len) //如果嘗試的是某個木棍的第一位置或者最後位置
break; //並且導致失敗,就不必嘗試剩餘的木棍了
上面的**裡只有這一句話是剪枝用的。下面對這一句有深刻內涵的**進行詳解。
我們首先已經把木棍長度從大到小排序了,然後每次去探測木棍的時候也都是從大到小去探測。假設當前我們要判斷l這個長度是否符合題意,木棍給了n個,總長度是sum。
顯然sum能被l整除,而且目標是讓所有木棍組成sum/l個l長度的木棍。
我們可以想象著sum/l個長度的東西為sum/l個桶,每個桶可以裝長度為l的木棍。
那麼上面這段剪枝temp==len這個條件的具體意思就是:我們在判斷搜到這個狀態是否能夠到達我們希望的終點時,我們需要去嘗試每乙個當前可以嘗試的木棍,那麼當我們放上乙個木棍失敗了,而且目前這根木棍又放在了桶底,那後面連試都不用試了,必定失敗。因為剩下的木棍是一定的,當前還要從桶底開始放,所以這一次放哪一根木棍對結果沒有影響,放這個木棍失敗了,後面的必定也失敗。
那麼上面這段剪枝sticks[i]==temp這個條件的具體意思是:當前這個木棍正好把乙個桶填滿了,然而失敗,那麼後面的都不用試了,必定失敗。這裡就是因為:我們的木棒是從大到小排序的。所以先試了長的木棒,不行。假設這根木棒長度為k,那麼後面短的木棒肯定得能組成長度為k的木棒,否則這段空就填不起來了。然而如果後面的木棒能組成長度為k的填好這個桶的空,那這些木棒跟這根k木棒就等價(否則這個k木棒就沒處放了),因此後面必定失敗。(這裡很繞,如果更詳細的話可以分類討論一下,總之就是不管什麼情況後面都必定失敗)
真是神奇的剪枝……
POJ 1011 木棒問題
問題描述 喬治拿來一組等長的棍子,將它們隨機地裁斷 截斷後的小段稱為木棒 使得每一節木棒的長度都不超過50個長度單位。然後他又想把這些木棒恢復到為裁截前的狀態,但忘記了棍子的初始長度。請你設計乙個程式,幫助喬治計算棍子的可能最小長度。每一節木棒的長度都用大於零的整數表示 輸入資料 由多個案例組成,每...
POJ 1011 搜尋剪枝
題意 給一堆木棒,這些木棒是由幾根長度相同的長木棒厥斷而成的,求最短的長木棒長度能厥成這些短的木棒。題解 所求長度肯定介於最長木棒和木棒之和中間,並且可以整除木棒之和。於是窮舉所有可能的值,選中乙個值之後,用dfs給木棒尋找組合,能找到就輸出。直接dfs會超時,所以需要剪枝。可以先排序,這樣相同的木...
POJ 1011 剪枝練習
題意 給定n條拆掉的棍子,問能湊成最短的多條相同長度棍子的最短長度 x 當前第幾條正在合成的棍子 y 目前正在嘗試的拆掉的棍子 z 當前長度 剪枝方案 1.按照長度單調性排序,減少重複搜尋 2.如果當前拼接棍子失敗,那接下來相同長度也會失敗 3.第一條棍子就失敗就不必搜尋了 h e a d int ...