•問題描述:
喬治拿來一組等長的棍子,將它們隨機地裁斷(截斷後的小段稱為木棒),使得每一節木棒的長度都不超過50個長度單位。然後他又想把這些木棒恢復到為裁截前的狀態,但忘記了棍子的初始長度。請你設計乙個程式,幫助喬治計算棍子的可能最小長度。每一節木棒的長度都用大於零的整數表示
輸入資料
由多個案例組成,每個案例包括兩行。第一行是乙個不超過64的整數,表示裁截之後共有多少節木棒。第二行是經過裁截後,所得到的各節木棒的長度。在最後乙個案例之後,是零。
輸出要求
為每個案例,分別輸出木棒的可能最小長度,每個案例佔一行。
輸入樣例9
5 2 1 5 2 1 5 2 1 4
1 2 3 4 0
輸出樣例6
5 剪枝1:
每次開始拼第i根棍子的時候,必定選剩下的木棒裡最長的一根,作為該棍子的第一根木棒。對此決不後悔。
就算由於以後的拼接失敗,需要重新調整第i根棍子的拚法,也不會考慮替換第i根棍子中的第一根木棒(換了也沒用)。
因為假設替換後能全部拼成功,那麼這被換下來的第一根木棒,必然會出現在以後拼好的某根棍子k中。那麼我們原先拼第i根棍子時, 就可以用和棍子k同樣的構成法來拼,照這種構成法拼好第i根棍子,繼續下去最終也應該能夠全部拼成功
剪枝2:
不要希望通過僅僅替換已拼好棍子的最後一根木棒就能夠改變失敗的局面。
剪枝3:
如果某次拼接選擇長度為l1的木棒,導致最終失敗,則在同一位置嘗試下一根木棒時,要跳過所有長度為l1的木棒。
剪枝4:
拼每一根棍子的時候,確保已經拼好的部分,長度是從長到短排列的
**:#include
#include
#include
using namespace std;
int len[100];
int length,n;
bool use[100];
bool cmp(int a,int b)
bool dfs(int notused,int nleft,int preno/*剪枝4*/)
if(preno!=0)
preno+=1;
int i;
for(i=preno;i0&&use[i-1]==false&&len[i]==len[i-1])
continue;//剪枝3
if(!use[i]&&len[i]<=nleft)}}
return false;
}int main()
sort(len,len+n,cmp);
for(i=len[0];i<=sum;i++)}}
return 0;
}
POJ1011 木棒(dfs 剪枝)
問題重述 description 喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計乙個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。inp...
POJ 1011 經典搜尋
這道題 是 比較經典的 搜尋題。題意 給出一堆小木棍的長度,需要把它們拼成幾根相同的大棍子,求 這些大棍子的最短長度 分析 這道題主要使用,深度搜尋 遞迴,當然這裡用到多次剪枝,這對於減小時間複雜度很有效。include includeusing namespace std int stick 64...
POJ 1011 搜尋剪枝
題意 給一堆木棒,這些木棒是由幾根長度相同的長木棒厥斷而成的,求最短的長木棒長度能厥成這些短的木棒。題解 所求長度肯定介於最長木棒和木棒之和中間,並且可以整除木棒之和。於是窮舉所有可能的值,選中乙個值之後,用dfs給木棒尋找組合,能找到就輸出。直接dfs會超時,所以需要剪枝。可以先排序,這樣相同的木...