喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。
然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。
請你設計乙個程式,幫助喬治計算木棒的可能最小長度。
每一節木棍的長度都用大於零的整數表示。
注意: 資料中可能包含長度大於50的木棒,請在處理時忽略這些木棒。
輸入格式
輸入包含多組資料,每組資料報括兩行。
第一行是乙個不超過64的整數,表示砍斷之後共有多少節木棍。
第二行是截斷以後,所得到的各節木棍的長度。
在最後一組資料之後,是乙個零。
輸出格式
為每組資料,分別輸出原始木棒的可能最小長度,每組資料佔一行。
輸入樣例:
9
5 2 1 5 2 1 5 2 1
41 2 3 4
0
輸出樣例:6
5
演算法:dfs + 剪枝
題解:剪枝:1、優先搜尋順序(從大大小),優先嘗試較長的木棒。
2、要求先後加入的木棒有單調性,因為你每根木棒都要用,之前加入和之後加入都是乙個樣。
3、當拼接乙個新木棒時,我加入乙個木棒,失敗了,說明,之後用到這個木棒拼接乙個新木棒的時候都會失敗。
4、當我現在我要加入的木棒拼接上去,正好等於拼接的長度,但是拼接失敗了,說明之後繼續拼接下去也是失敗。
#include #include#include
using
namespace
std;
const
int maxn = 1e5+7
;int
arr[maxn];
intvis[maxn];
intk, cnt;
bool cmp(int a, int
b) bool dfs(int stick, int cal, int last, int
len)
if(cal == len)
int fail = 0; //
剪枝2,記錄重複值
for(int i = last; i < k; i++)
vis[i] = 0
; fail =arr[i];
if(cal == 0 || cal + arr[i] == len) }}
return
false; //
當所有分支都嘗試過,並且還沒成功
}int
main()
sum +=x;
max_len =max(max_len, x);
arr[k++] =x;
}sort(arr, arr + k, cmp); //
剪枝1int
i;
for(i = max_len; i <= sum; i++)
cnt = sum / i; //
獲取木棒的數量
for(int j = 0; j < k; j++)
if(dfs(1, 0, 0
, i))
}printf(
"%d\n
", i);
}return0;
}
AcWing 167 木棒(搜尋)
深度搜尋 剪枝 原題鏈結 題目思路 從常用剪枝技巧開始 證明 2 反證法,若後面還有機會完整拼完,那麼一定會用到這一截木棍 第一截 矛盾。證明 3 反證法,若此處不用當前小截木棍,而換成其他截木棍組成等長的,再補上。那麼這截放到後面可以完整拼成的話,是矛盾的,因為這截與剛才 組成截 等價,而剛才是拼...
acwing167 深度搜尋 剪枝 木棒
喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計乙個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。輸入包含多組資料,每組資料報括兩行。第一...
167 兩數之和II (Two SumII)
暴力法兩次雜湊表 一次雜湊表 和1.兩數之和 leetcode 1.兩數之和 csdn不同之處在於,本題附加了有序的特殊限定。同樣可以借助於暴力法在時間複雜度o n 2 o left n right o n2 和空間o 1 o 1 o 1 解決。和雜湊表時間o n o left n right o ...