題型:搜尋題
題意:此題堪稱最經典搜尋題。
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 或...