题目链接:Sticks 木棒
Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过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函数很不合理,后来参考了国赛梦的博客 点击打开链接
这里主要采用了5个剪枝方法:
opt1:对输入数组进行由大到小的排序,这样求解的时候从最大数开始取,更容易得到解;
opt2:最终的解一定大于等于最小的木棒,小于等于所有木棒的和;
opt3:各节木棒长度的和一定是最终解的整数倍,因为原始木棒是等长的;
opt4:在DFS的过程中,如果当前木棒和前一个木棒长度相等,并且前一根木棒没有被使用,这说明此种长度的木棒不在此次遍历的解中,因此直接跳过;
opt5:(这个优化很重要,我一开始没做,导致TC中后两组数据TL)如果当前正在解第 i 根大木棒,遍历到第1根小木棒时(也是当前解空间中最长的小木棒),失败了。那么,直接回溯到去解第 i - 1 根大木棒。因为,最长的这根小木棒 + 所有剩余小木棒 求解失败了,就意味着在剩下这些小木棒中,只要包含这条最长小木棒,就无法得到解。
源代码:
#include <iostream>
#include <algorithm>
using namespace std;
int sticks[65];
bool used[65];
int n = 0;
int sum = 0;
int goal = 0;
int cmp(const int& a, const int& b)
{
return a > b;
}
bool DFS(int cur, int index, int cnt)
{
if(cnt == sum / goal)
return true;
for(int i = index; i < n; i++)
{
if(i && !used[i-1] && (sticks[i] == sticks[i-1])) continue; //opt4
if(used[i]) continue;
if(sticks[i] + cur > goal) continue;
used[i] = true;
if(sticks[i] + cur == goal)
{
if(DFS(0, 0, cnt + 1))
return true;
used[i] = false;
return false;
}
if(DFS(cur + sticks[i], i + 1, cnt))
{
return true;
}
else
{
used[i] = false;
if(cur == 0) return false; //opt5
}
}
return false;
}
int main()
{
while(1)
{
cin >> n;
if(!n) break;
sum = 0;
goal = 0;
memset(sticks, 0, sizeof(sticks));
for(int i = 0; i < n; i++)
{
cin >> sticks[i];
sum += sticks[i];
}
sort(sticks, sticks + n, cmp); //opt1
for(goal = sticks[0]; goal <= sum; goal++) //opt2
{
if(sum % goal != 0) //opt3
continue;
memset(used, 0, sizeof(used));
if(DFS(0, 0, 0))
{
cout << goal << endl;
break;
}
}
}
return 0;
}
最后再给出一组 Test Case,也是北京大学ACM论坛上的,请大家参考:
测试用例:
915 3 2 11 4 1 8 8 8
6
6 2 2 4 8 8
5
1 1 1 1 1
2
1 1
4
2 2 9 9
3
1 2 3
64
40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40
40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
40
7
49 48 47 46 45 44 43
7
3 4 5 5 5 5 13
7
2 7 7 7 7 10 20
6
1 2 3 11 11 20
7
63 2 44 12 60 35 60
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
64
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
33 33 31 31
64
40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40
40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40
40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40
40
45
15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8
15 3 2 11 4 1 8 8 8
0
结果:
20
10
1
1
11
3
1251
322
20
30
24
276
6
5
64
454
20