poj1011-Sticks dfs各种剪枝

来源:互联网 发布:新蛋现在怎么样 知乎 编辑:程序博客网 时间:2024/05/21 10:55

Sticks
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 133058 Accepted: 31236

Description

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

95 2 1 5 2 1 5 2 141 2 3 40

Sample Output

65


思路还可以,就是剪枝。。。。剪枝。。。。剪枝,咋想的啊。。。想破脑子也就想出来两个剪枝的地方,一直超时,大神一剪剪5个地方,一个

if (len == 0) break;,跪了。。。


思路:先从大到小排序,因为大的组合方式相对较少,先考虑(剪枝1)


InLen一定大于或者等于maxn,(否则你要组成的一条棍子还没有原来的长,不可能),并且要小于等于sum的一半,否则最后组成比如

17, 15这样的情况不用dfs,直接pass (剪枝2)

sum必须要能够整除InLen(剪枝3)

差不多了没啥事咱开始dfs吧

用一个sample来记录跳过当前层不能用的连续的棒子(剪枝4)

当一个InLen长的棒子合成之后开始合成新的InLen长的棒子时,若新的第一块碎片递归下去不能成功(也就是下面所有的的递归都返回false,因为包含这个碎片的所有的情况在返回的时候都考察过了,说明以上一根合成的结果为起点走下去不行,上一根棍子合成的有问题),则直接返回,否则继续走的话也不会成功,因为到最后,这第一块碎片迟早要面对的,在后面面对的时候跟第一次面对的时候没什么区别,第一次面对的时候不行,后面再面对的时候还是不行,因为第一次面对的时候已经把所有包含这第一块碎片的情况都考察进去了(剪枝5)


最后一种剪枝感觉不太好理解


#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;int s[100];bool vis[100];bool cmp(int a, int b) {return a > b;}int N;bool dfs(int len, int InLen, int num, int pos) {if (num == N) return true;for (int i = pos, sample = -1; i < N; i++) {if (!vis[i] && sample != s[i]) {vis[i] = true;if (len + s[i] < InLen) {if (dfs(len + s[i], InLen, num + 1, i)) {return true;} else {sample = s[i];}} else if (len + s[i] == InLen) {if (dfs(0, InLen, num + 1, 0)) {return true;} else {sample = s[i];}}vis[i] = false;if (len == 0) break;}}return false;}int main(){int sum, maxn;bool flag;while (~scanf("%d", &N) && N) {memset(vis, false, sizeof(vis));sum = 0;for (int i = 0; i < N; i++) {scanf("%d", &s[i]);sum += s[i];}sort(s, s + N, cmp); //降序排序 maxn = s[0];  //取最大的 flag = false;//maxn <= InLen <= sum / 2for (int InLen = maxn; InLen + InLen <= sum; InLen++) {if (!(sum % InLen) && dfs(0, InLen, 0, 0)) {flag = true;printf("%d\n", InLen);break;}}if (!flag) {printf("%d\n", sum);}}return 0;}


0 0
原创粉丝点击