poj1011 木棒 dfs+剪枝
阿新 • • 發佈:2019-01-29
目描述
喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計一個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。
Input
輸入包含多組資料,每組資料包括兩行。第一行是一個不超過64的整數,表示砍斷之後共有多少節木棍。第二行是截斷以後,所得到的各節木棍的長度。在最後一組資料之後,是一個零。
Output
為每組資料,分別輸出原始木棒的可能最小長度,每組資料佔一行。
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5
做法很顯然....就是dfs,列舉每一個長度來dfs,其他注意事項就在註釋裡面了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,a[101],f=0,num,used[101]; int dfs(int N,int now) { if(!now&&!N)return 1;//所有木棒都被選完了 if(!now)now=num;//組成了長度為now的一根木棒,開始找下一根木棒 for(int i=1;i<=n;i++) { if(!used[i]&&a[i]<=now) { if(i>1&&(!used[i-1]&&a[i-1]==a[i]))continue;//如果上一個沒有選且這個個和上一個一樣長那肯定也不選 used[i]=1; if(dfs(N-1,now-a[i]))return 1; else { used[i]=0; if(a[i]==now||now==num)return 0;//如果這一根不選,而且這一根還和剩餘長度一樣長,那麼後面的肯定不能選了。如果這一根不選,而且還沒有選,那麼後面的就選不了了 } } } return 0; } int main() { int i,j,k; while(scanf("%d",&n)) { if(!n)break; int s=0,maxl=0; for(i=1;i<=n;i++)scanf("%d",&a[i]),s+=a[i]; sort(a+1,a+1+n,greater<int>()); for(num=a[1];num<=s/2;num++)//至多s/2的長度,不然就是s了 { if(s%num==0)//num必定是s因數 { memset(used,0,sizeof(used)); if(dfs(n,num)) { printf("%d\n",num); break; } } } if(num>s/2)printf("%d\n",s); } return 0; }