标签:剪枝 last 进阶 0x22dfs int stick 木棍 include
题目链接;http://poj.org/problem?id=1011
又是拼木棍呀,不过这次我是对他的剪枝原理完全弄清楚了,最后两条剪枝还真的是很难想到的。这次的剪枝中加入了一条:我们在某一跟木棍中拼接时,选择的木棍长度是递减的,这样就保证了搜索树中不会有重叠的部分,不过其实在木棍中,小木棒是无序的,可以用这个策略来证明剪枝的正确性,也就是说,拼第一根失败和拼最后一根失败之后,这个分支就不可能搜索到最终状态了。
代码:
#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> using namespace std; #define maxn 100 int a[maxn],len,cnt,n; int vis[maxn]; int sum; int fail;//上一次拼接失败的木棍的长度 //last用来保证我们选择木棒的时候是按照递减的顺序选取的,防止搜索同样的状态空间 bool dfs(int stick,int cab,int last){//状态分别是当前在拼的是第几根木棍,当前木棍长度,开始选择的编号 if(stick==cnt+1)return true; if(cab==len)return dfs(stick+1,0,1);//新的木棍从第一根开始重新选择人拼接方案 fail=0; for(int i = last; i<=n;i++){ if(!vis[i] && cab+a[i]<=len && a[i]!=fail){//没用过并且能拼并且不是失败决策 vis[i]=1; if(dfs(stick,cab+a[i],i+1))return true; fail=a[i];//记录本次拼接失败的 木棒长度 vis[i]=0; if(cab==0 || cab+a[i]==len)return false; } } return false; } bool cmp(int &a,int &b){return a>b;} int main(){ while(cin>>n && n){ sum=0; int minlen=-0x7f7f7f7f; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i]; minlen=max(minlen,a[i]); } sort(a+1,a+n+1,cmp);//降序,优先考虑决策少的方案 for(int i=minlen;i<=sum;i++){ if(sum%i)continue; len=i; cnt=sum/len; memset(vis,0,sizeof(vis)); if(dfs(1,0,1))break; } cout<<len<<endl; } }
标签:剪枝,last,进阶,0x22dfs,int,stick,木棍,include 来源: https://www.cnblogs.com/randy-lo/p/13162204.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。