poj 1011 sticks(搜尋 剪枝)

2021-06-14 12:04:21 字數 1504 閱讀 8681

題型:搜尋題

題意:此題堪稱最經典搜尋題。

description

喬治拿來一組等長的木棒,將它們隨機地裁斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計乙個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。

input

輸入包含多組資料,每組資料報括兩行。第一行是乙個不超過64的整數,表示砍斷之後共有多少節木棍。第二行是截斷以後,所得到的各節木棍的長度。在最後一組資料之後,是乙個零。

output

為每組資料,分別輸出原始木棒的可能最小長度,每組資料佔一行。

sample input

95 2 1 5 2 1 5 2 1

41 2 3 4

0sample output65

分析:     一堆長度不等的木棍兒,如何分組使他們每一組的長度之和相等咧?窮舉是肯定的,但是暴力是不可能的。。。

設這一堆木棍的總長度為

sum,那麼可以想到,想要將其平均分配,每組的總長度肯定是sum的約數,因此只需列舉sum的所有約數就好了;

用dfs解決是靠譜的,但是單純的來寫的話就會光榮的得到乙個tle,因為計算過程中很大一部分是不必要的,因此本題的技巧就在於如何剪枝;

我們要找原來木頭可能的最小長度,那麼可以用乙個每組木棍長度之和的迴圈,迴圈的初始值是木棍中最大的長度,迴圈的邊界是所有木棍長度之和,如此便可保證得到可能最小長度的木棍兒。

把木棍兒長度按從大到小進行排序。既可以減少執行時間,又方便剪枝。

好了,關鍵來了,我們怎麼剪枝呢?

1、若要決策的木棍兒正好是需要的全部長度(即為當前拼接的最後乙個)後續迴圈是想要較短的去拼接起來,顯然即使拼了起來了,剩這個stick[i]遲早還是要用在某個地方的,所以不可行。

2、如果是重新開始找的,找到乙個較短的棍子是不可行的,那麼直接放棄這種方案,因為以某個短棍子不行的話,這個短棍子遲早還是要用到,那麼,當然還是不可行的。

**:

#include#include#include#include using namespace std;

bool used[1000];

int a[1000];

int n,sum;

int cmp(const void *a,const void *b)

bool dfs(int unused,int left,int len,int pos)

if(left==0)

for(int i=pos;ileft)

used[i]=true;//標記

if(dfs(unused-1,left-a[i],len,i+1))

used[i]=false;//狀態恢復

if(len==left||a[i]==left)

}return false;

}int main()}}

}return 0;

}

poj1011 Sticks 搜尋 剪枝

題目大意 george有一捆相同長度的木棍,但是他把這些木棍砍段了,現在想知道這些木棍原來長度是多少 即還原木棍 求可能的最小的原木棍長度。如下 include include include include includeusing namespace std int n,stick 64 use...

暴力搜尋 POJ 1011 Sticks

首先這道題目有兩個非常重要的剪枝1 如果當前放的是木塊的第乙個那如果當前dfs不成立,那麼直接返回false因為每乙個木板必定屬於乙個塊,當他放第乙個的時候如果可以放其他的其實是已經固定了的了,如果當前不成立那麼不存在隊友可以和他一起站對。2 就是如果當前這個和前一次進行dfs的木板長度一樣,就跳過...

poj 1011 Sticks 減枝搜尋

題意 有n根棍子,分別有長度。問將其拼接成x根,長度相同,求最小長度。解法搜尋。1.因為總共n根棍子,最多拼接成n根相同長度,並且,組成的棍子數量越多,則長度則越小 2.拼接的棍子數量必定能夠 被 sum 整除 3.若當前棍子長度 stick i 不能夠匹配,在 stick i left len 或...