深度迭代搜索+剪枝
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int n,m; 6 int a[55],value[1025]; 7 int b[55]; 8 int limit=1; 9 int space=0; 10 int maxspace=0; 11 bool cmp(int a,int b) 12 { 13 return a>b; 14 } 15 int dfs(int cur,int start) 16 { 17 if(cur==m) 18 { 19 return 1; 20 } 21 space=0; 22 for(int i=0;i<n;i++) 23 { 24 if(b[i]<value[m-1]) space+=b[i]; 25 } 26 if(space>maxspace) return 0; 27 for(int i=start;i<n;i++) 28 { 29 if(b[i]>=value[cur]) 30 { 31 int st=0; 32 b[i]-=value[cur]; 33 if(cur<m-1&&value[cur]==value[cur+1]) st=i; 34 if(dfs(cur+1,st)) return 1; 35 b[i]+=value[cur]; 36 } 37 } 38 return 0; 39 } 40 int main() 41 { 42 scanf("%d",&n); 43 for(int i=0;i<n;i++) 44 { 45 scanf("%d",&a[i]); 46 } 47 sort(a,a+n,cmp); 48 scanf("%d",&m); 49 for(int i=0;i<m;i++) 50 { 51 scanf("%d",&value[i]); 52 } 53 sort(value,value+m,cmp); 54 int left=0; 55 int right=m; 56 while(left<right) 57 { 58 int mid=left+(1+right-left)/2; 59 limit=mid; 60 maxspace=0; 61 for(int i=0;i<n;i++) maxspace+=a[i]; 62 for(int i=m-limit;i<m;i++) maxspace-=value[i]; 63 for(int i=0;i<n;i++) b[i]=a[i]; 64 if(dfs(m-limit,0)) left=mid; 65 else right=mid-1; 66 } 67 printf("%d\n",left); 68 return 0; 69 }
五个剪枝方法
一个是当前余量不能超过最大余量(这个非常有效)
二分搜索(不是非常有效)
重复元素:start可以不从第一个开始枚举
背包的大小,物品的大小:背包从大的开始装,选k个物品时,当然时选k个最小的,在dfs内要从k个物品中的大的开始枚举
删除不可能装进的物品
时间: 2024-10-13 14:33:11