POJ 1011 Sticks

Posted lipeiyi520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1011 Sticks相关的知识,希望对你有一定的参考价值。

题目传送门

//原址有中文翻译

解题思路:

求出总长度sum和小棒最长的长度max,则原棒可能的长度必在max~sum之间,然后从小到大枚举max~sum之间能被sum整除的长度len,用dfs求出所有的小棒能否拼凑成这个长度,如果可以,第一个len就是答案。

 

下面就是关键的了,就是这道题dfs的实现和剪枝的设计:

      1.以一个小棒为开头,用dfs看看能否把这个小棒拼凑成len长,如果可以,用vis[i]记录下用过的小棒,然后继续以另外一个小棒为开头,以此类推。

      2.小棒的长度从大到小排序,这个就不解释了。

      3.如果当前最长的小棒不能拼成len长,那么就返回前一步,更改前一步的最长小棒的组合情况(这里不能是全部退出),不用再继续搜索下去了。

      4.最重要的,就是比如说17,9,9,9,9,8,8,5,2……如果当前最长小棒为17,它与第一个9组合之后dfs发现不能拼成len,那么17就不用和后面所有的9组合了,而直接和8开始组合。这个剪枝直接从TLE到16MS,很强大。

//转自http://blog.sina.com.cn/s/blog_6635898a0100lgq0.html

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 int n,a[70],ans;
 9 bool flag,vis[70]; 
10 
11 bool cmp(int k,int b) 
12     return k > b;
13 
14 
15 inline void dfs(int deep,int now,int i) 
16     if(flag) return ;
17     if(now == 0) 
18         int k = 0;
19         while(vis[k]) k++;
20         vis[k] = true;
21         dfs(deep + 1,a[k],k + 1);
22         vis[k] = false;
23         return ;
24     
25     if(now == ans) 
26         if(deep == n + 1) flag = true;
27         else dfs(deep,0,1);
28         return ;
29     
30     for(int j = i;j <= n; j++) 
31         if(!vis[j] && now + a[j] <= ans) 
32             if(!vis[j-1] && a[j] == a[j-1]) continue;
33             vis[j] = true;
34             dfs(deep + 1,now + a[j],j + 1);
35             vis[j] = false;
36         
37     
38 
39 
40 int main()
41 
42     while(true) 
43         scanf("%d",&n);
44         if(n == 0) return 0;
45         flag = false;
46         int sum = 0;
47         for(int i = 1;i <= n; i++) 
48             scanf("%d",&a[i]);
49             sum += a[i];
50         
51         sort(a + 1,a + n + 1,cmp);
52         for(ans = a[1];ans < sum; ans++) 
53             if(sum % ans == 0) 
54                 memset(vis,0,sizeof(vis));
55                 dfs(0,0,1);
56                 if(flag) break;
57             
58         printf("%d\n",ans);
59     
60     return 0;
61 

 

以上是关于POJ 1011 Sticks的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1011 Sticks

poj1011 Sticks

poj1011(DFS+剪枝)

POJ1011 SticksDFS+剪枝

poj-1011 sticks(搜索题)

POJ 1011 Sticks