0/1背包总结(持续更新...)

数字分组问题

Problem 1:给定n个物品,将它们分成两堆,使他们的质量之差最小,求这个最小值

poj 2311

Sol:差最小是0,此时分成的两堆的质量都是sum/2,因此让背包的总容量为sum/2,就是让某一堆尽量接近sum/2,此时两堆的差最小

Code:

#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;
}
View Code

 

Problem 2:给定n个物品,将它们分成两堆,使他们的质量之差最大,但不能超过这些物品中最大的质量

没找到题,求资源

 Sol:相差最大时,两堆物品的质量分别是(sum+max)/2,(sum-max)/2,因此让背包容量为(sum+max)/2即可

Code:

 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 */
View Code

 

posted @ 2017-09-02 12:17  spli  阅读(218)  评论(0编辑  收藏  举报