【POJ1011】Sticks

确实是一道经典的深搜好题,(不过POJ不都是这样吗……)。

首先这道题爆搜就死定了,所以咱们考虑一些剪枝。

1.对所有的木棍按长度降序排序,先尝试较长的木棍,这样可以减少搜索树的分支。

2.定义一个变量,记录最近一次搜索失败的木棍的长度,若即将搜索的长度与之相等,则直接跳过。

3.如果在原始木棒“加入第一根”就搜索错误,那么直接返回错误,因为剩下的原始木棒都是一样的。

4.如果加入一根木棒,当前的原始木棒恰好拼接完成,而之后的拼接返回错误,则直接返回错误。因为用一根长木棍拼接完成一定比用若干根短木棍拼接完成更好。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 typedef long long ll;
 6 using namespace std;
 7 int n,a[70],maxx,minn,tot,len;
 8 bool vis[70];
 9 bool dfs(int done,int now,int last) {
10     if(done>tot) return 1;
11     if(now==len) return dfs(done+1,0,1);
12     int x=0;
13     for(int i=last;i<=n;i++)
14         if(!vis[i]&&x!=a[i]&&a[i]+now<=len) {
15             vis[i]=1;
16             if(dfs(done,now+a[i],i+1)) return 1;
17             x=a[i];
18             vis[i]=0;
19             if(now==0||now+a[i]==len) return 0;
20         }
21     return 0;
22 }
23 int main() {
24         memset(a,0,sizeof(a));
25         maxx=minn=0;
26         for(int i=1;i<=n;i++) {
27             cin>>a[i];
28             maxx+=a[i];
29             minn=max(a[i],minn);
30         }
31         sort(a+1,a+n+1);
32         reverse(a+1,a+n+1);
33         for(len=minn;len<=maxx;len++) 
34             if(maxx%len==0) {
35                 tot=maxx/len;
36                 memset(vis,0,sizeof(vis));
37                 if(dfs(1,0,1)) break ;
38             }
39         cout<<len<<endl;
40     return 0;
41 }
AC Code

 

posted @ 2019-03-23 10:38  AD_shl  阅读(183)  评论(0编辑  收藏  举报