時間限制: 1 sec 記憶體限制: 128 mb
提交: 7 解決: 5
[提交][狀態][討論版][命題人:add_cy]
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。
現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。
給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。
輸入檔案共有二行。
第一行為乙個單獨的整數n表示砍過以後的小木棍的總數,其中n≤60。
第二行為n個用空個隔開的正整數,表示n根小木棍的長度。
輸出檔案僅一行,表示要求的原始木棍的最小可能長度。
9
5 2 1 5 2 1 5 2 1
6
從最優性方面:
1.設所有木棍長度和為sum,那麼原長度(也就是需要輸出的長度)一定能夠被sum整除,這樣得到的木棍根數才是整數
2.木棍原來的長度一定不小於所有木棍中最長的那根
綜上兩點,可以確定原木棍的長度len在最長木棍的長度maxlen和sum之間取值,且sum能被len整除。所以在搜尋原木棍的長度時,可以從砍過以後所有木棍中最長的長度開始,每次增加長度後,必須能整除sum。這樣可以有效優化程式。
從可行性方面:
1.短木棍更加靈活,長木棍受到的限制更大,所以可以對輸入的所有木棍按長度從大到小排序。
2.在砍斷後的排好序的木棍中,當用木棍i拼合原始木棍時,可以從i+1的木棍開始往後搜,因為i前面的木棍已經用過了
3.從當前最長長度的木棍開始搜,如果拼不出當前設定的原木棍長度len則直接返回,換乙個原始木棍長度len
4.相同長度的木棍不要搜尋多次.用當前長度的木棍搜下去得不出結果時,用一支同樣長度的還是得不到結果,所以可以提前返回
5.判斷搜到的幾根木棍組成的長度是否大於原始長度len,如果大於沒必要搜下去,可以提前返回
6.判斷當前剩下的木棍根數是否夠拼成木棍,如果不夠,肯定拼合不成功,直接返回
7.找到結果後,在能返回的地方馬上返回到上一層的遞迴處
#include#include#include#include#include#includeusing namespace std;
int n,m,len,sum=0,maxlen=0,flag;
int a[61],visit[61];
int cmp(int a,int b)
void dfs(int k,int last,int rest)//k為第k根木棍,last為第k根上一節木棍編號;rest為第k根木棍還需要的長度
//木棍根數達到要求,剪枝
if(rest==0)開始下一根木棍
sort(a,a+n,cmp);//對木棍按從大到小排序,可行性剪枝1
for(int i=maxlen;i<=sum;i++)//列舉原始木棍的長度,最優性剪枝}}
return 0;
}
深搜的剪枝技巧 小木棍
時間限制 1 sec 記憶體限制 128 mb 喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。輸入檔案共有二行。第一行為乙...
小木棍 搜尋剪枝
小木棍,多麼經典的題目啊,幾年都拿出來做一下,今年終於感覺有點明白了 真為中年婦女的智商著急啊 題解抄的luogu題解,修改了以前抄的 終於ac了.主要難點在於如何進行dfs的剪枝可以二分答案 不二分也不會超時,我的 沒有二分 dfs看看這個答案可不可行雖然資料很小,直接dfs也是會超時的,所以需要...
深搜的剪枝
深搜前面已經講過,對於剪枝,就是把沒必要的步驟進行if特判剪枝,用好了可以大大的優化複雜度 這裡就根據兩個例題來講吧 詳情見 include include include intn,k int f 210 7 int main printf d n f n k 輸出最大值 return0 詳情見 ...