George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
简述:给你n个木棒及其长度,求其能组成的最短的相同长度的木棒的长度。
分析:既然是最短搜索,用DFS+回溯即可,找出其最大的木棒长度,其可能的长度在最大长与长度和之间,与F题不同,这题需要有三点剪枝才能AC
1.不重复访问。
2.若长度为a的木棒不满足题意,则大于等于它的都不会满足,例如:2 2 2 2 1,若第一个2不满足,则需要直接跳过到1.
3.因为我们将木棒降序排序,第一根(最大)必然会用上,如果第一根木棒未被用上直接剪枝退出即可
注意考虑其只合成一根木棒的情况,代码如下:
const int maxm = 70; int vis[maxm], n, buf[maxm], tmp, len; bool comp(int a,int b) { return a > b; } bool dfs(int cur,int pos,int t) { if(t == tmp) return true; if(cur == len) return dfs(0, 0, t + 1); int pre = 0; for (int i = pos; i < n; ++i) { if(!vis[i]) { // first int nlen = cur + buf[i]; if(pre != buf[i] && nlen <= len) { // second pre = buf[i]; vis[i] = 1; if(dfs(nlen,i+1,t)) return true; vis[i] = 0; if(!pos) //third return false; } } } return false; } int main() { while(scanf("%d",&n) && n) { int sum = 0; for(int i = 0; i < n; ++i) { scanf("%d", &buf[i]); sum += buf[i]; } sort(buf, buf + n,comp); for (len = buf[0]; len <= sum / 2; ++len) { // 若大于sum/2必然只能合成一根木棒 if(sum % len) continue; tmp = sum / len; memset(vis, 0, sizeof(vis)); if(dfs(0,0,0)) break; } if(len > sum / 2) printf("%d ", sum); else printf("%d ", len); } return 0; }