0/1背包总结(持续更新...)
数字分组问题
Problem 1:给定n个物品,将它们分成两堆,使他们的质量之差最小,求这个最小值
Sol:差最小是0,此时分成的两堆的质量都是sum/2,因此让背包的总容量为sum/2,就是让某一堆尽量接近sum/2,此时两堆的差最小
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<map> using namespace std; int m,n; int col; map<string,int>mch; int v[15][110],sum[15]; int f[500*1010]; int main(){ scanf("%d%d",&m,&n); while(n&&m){ col=0;//memset(mch,0,sizeof(mch)); mch.clear(); memset(v,0,sizeof(v)); memset(sum,0,sizeof(sum)); string s; for(int i=1;i<=m;++i){ cin>>s; mch[s]=++col; s.clear(); } int x; for(int i=1;i<=n;++i){ scanf("%d",&x);cin>>s; v[mch[s]][++v[mch[s]][0]]=x; sum[mch[s]]+=x; s.clear(); } int ans=0; for(int t=1;t<=col;++t){ memset(f,0,sizeof(f)); for(int i=1;i<=v[t][0];++i) for(int j=sum[t]/2;j>=v[t][i];--j) f[j]=max(f[j],f[j-v[t][i]]+v[t][i]); ans+=sum[t]-f[sum[t]/2]; } printf("%d\n",ans); scanf("%d%d",&m,&n); } return 0; }
Problem 2:给定n个物品,将它们分成两堆,使他们的质量之差最大,但不能超过这些物品中最大的质量
没找到题,求资源
Sol:相差最大时,两堆物品的质量分别是(sum+max)/2,(sum-max)/2,因此让背包容量为(sum+max)/2即可
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstring> 2 #include<cstdio> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 int n,m,mx=-0x3f3f3f3f,sum; 8 int a[30]; 9 bool f[20*100010]; 10 11 int main(){ 12 scanf("%d",&n); 13 for(int i=1;i<=n;++i) scanf("%d",&a[i]),sum+=a[i],mx=max(mx,a[i]); 14 m=(sum+mx)/2; 15 f[0]=1; 16 for(int i=1;i<=n;++i) 17 for(int j=m;j>=a[i];--j) 18 f[j]|=f[j-a[i]]; 19 for(int i=(sum-mx)/2;i<=sum/2;++i) 20 if(f[i]&&f[sum-i]){ 21 cout<<sum-2*i;return 0; 22 } 23 return 0; 24 } 25 26 27 /* 28 5 29 2 4 5 8 10 30 */