喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。
現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。
給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。
共二行。
第一行為乙個單獨的整數n表示砍過以後的小木棍的總數,其中n≤65
(管理員注:要把超過50的長度自覺過濾掉,坑了很多人了!)
第二行為n個用空個隔開的正整數,表示n根小木棍的長度。
乙個數,表示要求的原始木棍的最小可能長度輸入9
5 2 1 5 2 1 5 2 1輸出6
一道比較複雜的題目(主要難度在於對**進行剪枝),先輸入所有木棍的長度,從其中最大的開始搜尋,判斷以當前長度是否所有木棍能拼接成,如果可以就輸出當前長度,退出迴圈。
#include
using namespace std;
int n,a[70]
,c[70
],m;
int sum=
0,maxmum=
0,len;
bool flag,b[70]
;//陣列b用來表示該位置的小木棍有沒有被使用組合原始木棍。
void
dfs(
int t,
int last,
int rest)
int k=n;
for(
int i=
1; i<=n; i++)}
b[k]=1
;//標記
dfs(t+
1,k+
1,len-a[k]);
//下乙個情況
b[k]=0
;//回溯
return;}
int l=last,r=n,mid;
while
(l//使用二分,找到第一根長度小於等於原始木棍長度的木棍
/*如果當前長棍剩餘的未拼長度等於當前木棍的長度或原始長度,繼續拼下去時卻失敗了,就直接回溯之前拼的木棍。*/
for(
int i=l; i<=n; i++
) i=c[i]
; i--;}
}}intmain()
a[++n]
=x; sum+
=a[n]
;//統計所有成功輸入的木棍的長度和
if(maxmumsort
(a+1
,a+n+
1,greater<
int>()
);//便於下乙個優化
for(
int i=
1; i<=n; i++
) c[j]
=k;}
else
}for
(len=maxmum;len<=sum/
2;len++
) m=sum/len;
//計算得到一共可以組成多少根原始木棍
memset
(b,false,
sizeof
(b))
;dfs(1
,1,len);}
if(!flag)
/*如果上一步的搜尋都沒有得到正確的輸出,那麼就輸出所有木棍的長度和,即所有木根合在一起拼接成一根木棍。*/
return0;
}
洛谷 P1120 小木棍 資料加強版
題目 小木棍 思路 搜尋 剪枝。外層迭代加深,列舉最小長度,用dfs判斷。dfs維護3個變數x,y,lst,即用了x根木棍,當前拼到了y,上一根木棍的長度為lst。然後列舉拼接的木棍就好。剪枝一 從大到小排序。剪枝二 如果y不為0,那麼列舉的木棍長不要大於lst,不然就會重複搜尋。剪枝三 如果y 0...
洛谷 P1120 小木棍 資料加強版
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過5050。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。搜尋加剪枝 剪枝 1 使用桶排,因為長度不超過50。2 列舉的長度應該能...
洛谷p1120小木棍 資料加強版 c
dfs剪枝 主要難點在於如何進行dfs的剪枝,典型例題如小木棍 洛谷p1120小木棍 可以二分答案 不二分也不會超時,我的 沒有二分 dfs看看這個答案可不可行 雖然資料很小,直接dfs也是會超時的,所以需要加入一些剪枝。1.從max 最大木棍長度,總木棍長度 要分的段數 為左面,所有木棍長度為右面...