【深度搜索+剪枝】POJ1011-Sticks

深搜部分和之前的POJ2362差不多,只是有几处需要额外的剪枝。

【思路】排序后从最短木棒开始搜索至木棒长总和,如果木棒长总和sum能整除当前棒长,则进入深搜。

【剪枝】先前POJ2362的剪枝部分不再重提,这里只讲额外的几处(我们称切断后的棒为木棒,切断前的棒为原棒):

1.如果所有木棒等长,即排序后stick[0]=stick[n-1],则直接输出棒长;

2.如果当前搜索的棒长即是棒长总和,无需进入深搜子程序,直接输出;

3.如果深搜中当前长度的木棒不能选择,则略去同一层中相同长度的木棒;

4.如果当前是重新开始组成一个原棒,即len=0时。如果可以组成原棒,则取frm时必然能返回真(因为组成原棒的顺序是无所谓的);若选取frm时仍然无法组成,则说明不能组成原棒,直接退出深搜,返回假。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=64+5;
 7 int n,sl;
 8 int stick[MAXN];
 9 int vis[MAXN];
10 
11 int dfs(int side,int frm,int len)
12 {
13     if (1==side) return 1;
14     int last=-1;
15     for (int i=frm;i>=0;i--)
16         if (!vis[i] && stick[i]!=last)
17         {
18             vis[i]=1;
19             if (sl==len+stick[i])
20             {
21                 if (dfs(side-1,n-1,0)) return 1;
22             }
23             else  if (sl>len+stick[i])
24             {
25                 if (dfs(side,i-1,len+stick[i])) return 1;
26             }
27             vis[i]=0;
28             last=stick[i]; 
29             if (len==0) break;
30         }
31     return 0;
32 }
33 
34 int main()
35 {
36     while (scanf("%d",&n))
37     {
38         if (0==n) break;
39         int sum=0;
40         for (int i=0;i<n;i++) 
41         {
42             scanf("%d",&stick[i]);
43             sum+=stick[i];
44         }
45         sort(stick,stick+n);
46         if (stick[0]==stick[n-1])
47         {
48             cout<<stick[0]<<endl;
49             continue;
50         }
51         for (int i=stick[0];i<=sum;i++)//i代表每一根木棒的长度 
52             if (0==sum%i) 
53             {
54                 sl=i;
55                 memset(vis,0,sizeof(vis));
56                 if (i==sum || dfs(sum/i,n-1,0)) 
57                 {
58                     cout<<i<<endl;
59                     break;
60                 }
61             }
62     }
63     return 0;
64 }

 

posted @ 2015-07-06 15:16  iiyiyi  阅读(305)  评论(0编辑  收藏  举报