DFS 剪枝1 poj 1011

Sticks
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 100527   Accepted: 22858

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

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

题意:

将长度相等的枝条剪成n段,每段长均给出,现求没被剪时的枝条的最短长度。

思路:

一道很明显的DFS题。将木条拼接成合适的长度。

因为要求的木条的初始长度最短不会短过给出长度的最长长度,所以木条的原始长度可以从给出长度的最长长度开始枚举。

枚举后,一层层向下搜索,观察是不是最后能够将木条完全拼接完,如果可以,则枚举长度则为所求长度,不行,则继续枚举。

但是搜索的过程需要剪枝:

1. 木条应该先从大到小的进行排序,然后将木条进行拼接时,应先从大的进行选择,这样情况在刚开始就会减少很多。

2. 然后是各种细节剪枝,坑啊。。。本人不知道考虑了多少种剪枝,结果都不停的TLE,后来终于想到一种:在拼接木条时,如果刚开始拼接木条就找不到合适的,那么直接不再考虑这种情况,向下一种情况考虑。

3. 还有各种剪枝,代码中列出。


代码实现:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 using namespace std;
 6 int a[100];
 7 int vis[100];
 8 int sumsome[100];
 9 int sum;
10 bool cmp(const int & b,const int &c){
11      return b>c;
12 }
13 int n;
14 int DFS(int m,int dolen,int len,int flag){
15     if(m==0){
16        if(len==0)
17             return 1;
18        else
19             return -1;
20             }
21     if(len==0){
22           // len=dolen;
23            //flag=0;
24        //    }
25        if(DFS(m,dolen,dolen,0)==1)
26           return 1;
27       else
28           return -1;
29        }
30     for(int k=flag;k<n;k++){
31             if(a[n-1]>len)
32                 break;
33             if(k!=0){
34             if(sum-sumsome[k-1]<len)
35                 break;
36                  }
37             if(vis[k]==1)
38                   continue;
39             if(a[k]<=len){
40                    vis[k]=1;
41                    int temp=DFS(m-1,dolen,len-a[k],k+1);
42                    if(temp==1){
43                            return 1;
44                            }
45                    else {
46                            vis[k]=0;
47                            if(a[k]==len||len==dolen)                //really important!!!!!! 
48                                     break;
49                            while(k+1<n&&a[k+1]==a[k]){
50                                k++;
51                              //  k=k+1;
52                                }
53                            continue;
54                    }
55                    }
56                    }
57     return -1;
58 }
59 int main(){
60     while(scanf("%d",&n)!=EOF){
61        if(n==0)
62             break;
63         sum=0;
64         memset(sumsome,0,sizeof(sumsome));
65         for(int i=0;i<n;i++){
66                scanf("%d",&a[i]);
67                 sum+=a[i];
68                 }
69         sort(a,a+n,cmp);
70         for(int j=0;j<n;j++){
71                 sumsome[j]+=a[j];
72                 }
73         int maxlen=a[0];
74         int minlen=a[n-1];
75         int res=maxlen;
76         for(int i=maxlen;i<=sum;i++){
77                 memset(vis,0,sizeof(vis));
78                 if(sum%i==0){
79                 if(DFS(n,i,i,0)==1){
80                      res=i;
81                      break;
82                      }
83                      }
84                 }
85         printf("%d\n",res);
86         }
87     return 0;
88 }

 

posted on 2012-09-04 19:40  yumao  阅读(320)  评论(0)    收藏  举报

导航