首页 > 代码库 > USACO/fence8 迭代加深搜索+剪枝
USACO/fence8 迭代加深搜索+剪枝
题目链接
迭代加深搜索思想。
枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切。
1、对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案。
2、对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优。
3、假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能【浪费】的最大数目。对于一个切剩下的原材料,若它比最小的目标木头还要小,则它可视为【无用】的,无用的也就是浪费的,若浪费>all-sum,则直接返回false
4、对于一个目标木头B,若它的长度和上一个木头A的长度相同,那么我们切B所用的原材料(B‘)一定是从切A所用的原材料(A‘)位置开始找。(这其实就是一个剪掉重复计算的剪枝)
5、迭代可以使用二分,但其实枚举也慢不了多少。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int n,m,a[55],b[1100],maxs=0,sums[1100]; int mid; bool cmp(int x,int y) { return x>y; } bool dfs(int ia,int ib,int sum,int all) { if(ib==0) return true; if(sum>all) return false; for(int i=ia;i<=n;i++) { if(a[i]>=b[ib]) { a[i]-=b[ib]; int tmp=sum+(a[i]<b[1]?a[i]:0); int st=(b[ib]==b[ib-1]?i:1); if(dfs(st,ib-1,tmp,all)) { a[i]+=b[ib]; return true; } a[i]+=b[ib]; } } return false; } int main() { freopen("fence8.in","r",stdin); freopen("fence8.out","w",stdout); int all=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); all+=a[i]; maxs=max(maxs,a[i]); } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&b[i]); if(b[i]>maxs) {i--;m--;} } sort(a+1,a+1+n,cmp); sort(b+1,b+1+m); for(int i=1;i<=m;i++) sums[i]=sums[i-1]+b[i]; int l=0,r=m,ans; for(ans=0;ans<=m&&dfs(1,ans,0,all-sums[ans]);ans++) ; printf("%d\n",ans-1); return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。