POJ1011 木棒(dfs 剪枝)

2022-08-12 11:30:13 字數 2189 閱讀 7949

問題重述:

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 ...