木棒(深搜 剪枝)
阿新 • • 發佈:2020-12-22
喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。
然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。
請你設計一個程式,幫助喬治計算木棒的可能最小長度。
每一節木棍的長度都用大於零的整數表示。
輸入格式
輸入包含多組資料,每組資料包括兩行。
第一行是一個不超過64的整數,表示砍斷之後共有多少節木棍。
第二行是截斷以後,所得到的各節木棍的長度。
在最後一組資料之後,是一個零。
輸出格式
為每組資料,分別輸出原始木棒的可能最小長度,每組資料佔一行。
資料範圍
資料保證每一節木棍的長度均不大於50。
輸入樣例:
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
輸出樣例:
6
5
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N = 100; bool state[N]; int w[N]; int sum; int n; int length ; bool dfs(int u ,int s , int start) { if(u * length == sum)return true; if(s == length) return dfs(u+1,0,0); for(int i = start ; i < n ; i ++) { if(s + w[i] > length) continue; if(state[i])continue; if(!state[i]) { state[i] = true; if(dfs(u,s+w[i], i +1)) return true;; state[i] = false; } if(!s) return false;//第一個木棍失敗回溯 長度為0 後面的都失敗 if(s + w[i] == length) return false; // 最後一個木棍失敗 int j = i; while( j < n && w[i] == w[j] ) j ++;//相同木棍失敗 i = j-1; } return false; } int main() { while(cin >> n , n) { memset(state,0,sizeof state); sum = 0; for(int i =0 ; i < n ; i ++) { cin >> w[i]; sum +=w[i]; } sort(w,w+n); reverse(w,w+n);//搜尋剪枝 length = 1;//列舉大棍長度 while(true) { if(sum % length == 0 && dfs(0,0,0))//可行性剪枝 { cout << length<<endl; break; } length++; } } return 0; }