poj 1011 小木棍
这个剪枝也是够了,不过不愧是搜索经典题,做完此题之后,感觉对深搜有了更多的理解,感觉学动规之前一定要学搜索,好的搜索题一定需要你好好的定义状态,在这里一定要把状态的知识学扎实了
再来说小木棍,小木棍有一个基础剪枝,就是找到上界和下界的位置
剪枝一:先得拼大的
剪枝二:如果一根新的长度没有拼成功,那么这个长度就不可用
剪枝三:在拼的过程中,如果中间有一段有相同的部分,并且一个没有成功,后面的不用尝试的
ps:洛谷的题目好坑
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=65; int a[maxn],vis[maxn],n,num,ans; int cmp(int a,int b) { return a>b; } bool dfs(int res,int curn,int pos) { bool flag=false; if(res==ans) flag=true;//表示还没有开始拼接 if(a[n]>res) return false; if(curn==num) return true; for(int i=pos;i<=n;i++) { if(vis[i]==false&&a[i]==res) { vis[i]=true; if(dfs(ans,curn+1,1)) return true;//这里只能这样写,dfs才能连上 vis[i]=false;//拼接不成功 回溯 return false;//这里可以剪枝吗? }else if(vis[i]==false&&a[i]<res) { vis[i]=true; if(dfs(res-a[i],curn,i+1)) return true; vis[i]=false; if(flag==true) return false; while(a[i]==a[i+1]) i++;//如果前一个没有拼接成功,那么和他相同的也成功不了 } } return false;//dfs循环断层的问题 } int main() { while(scanf("%d",&n)!=EOF) { if(n==0) break; memset(vis,0,sizeof(vis)); memset(a,0,sizeof(a)); int sum=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]>50) {n--,i--;} else sum=sum+a[i]; } sort(a+1,a+1+n,cmp); for(int i=a[1];i<=sum;i++) { if(sum%i==0) { ans=i; num=sum/i; if(dfs(ans,0,1)) { printf("%d\n",ans); break; } } } } }

浙公网安备 33010602011771号