背包专题练习

hdu1171多重背包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn=100005;
const int INF=~0u>>1;
int w[maxn],v[maxn],num[maxn],dp[500007];
int main(){
    int N;
    while(~scanf("%d",&N)){
        if(N<=0) break;
        int sum=0;
        for(int i=0;i<N;++i){
            scanf("%d%d",&w[i],&num[i]);v[i]=w[i];sum+=num[i]*v[i];
        }
        int V=sum/2;
        for(int i=0;i<500007;++i) dp[i]=-INF;dp[0]=0;
        for(int i=0;i<N;++i){
            if(num[i]*w[i]>V) for(int j=w[i];j<=V;++j) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            else{
                int t=1;
                while(t<num[i]){
                    for(int j=V;j>=t*w[i];--j) dp[j]=max(dp[j],dp[j-t*w[i]]+t*v[i]);
                    num[i]-=t;
                    t<<=1;
                }
                for(int j=V;j>=num[i]*w[i];--j) dp[j]=max(dp[j],dp[j-num[i]*w[i]]+num[i]*v[i]);
            }
        }
        int A=-INF;
        for(int i=0;i<=V;++i) A=max(A,dp[i]);
        int B=sum-A;
        if(A<B) swap(A,B);
        printf("%d %d\n",A,B);
    }
    return 0;
}
View Code

hdu1059二进制优化多重背包

#include <iostream>
#include <cstdio>

using namespace std;
const int maxn=10;
const int INF=~0u>>1;
int w[10],v[10],num[10],dp[120007];
int main(){
    for(int i=0;i<6;++i){
        w[i]=i+1;v[i]=i+1;
    }
    int cas=0;
    while(~scanf("%d",&num[0])){
        int t=num[0];
        for(int i=1;i<6;++i) scanf("%d",&num[i]),t+=num[i];
        if(!t) break;t=0;
        printf("Collection #%d:\n",++cas);
        for(int i=0;i<6;++i) t+=num[i]*(i+1);
        if(t&1) {
            printf("Can't be divided.\n\n");continue;
        }
        for(int i=0;i<120007;++i) dp[i]=-INF;
        dp[0]=0;
        int mid=t/2,V=mid;
        for(int i=0;i<6;++i){
            if(num[i]*w[i]>V) for(int j=w[i];j<=V;++j) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            else{
                if(!num[i]) continue;
                t=1;
                while(t<num[i]){
                    for(int j=V;j>=t*w[i];--j) dp[j]=max(dp[j],dp[j-t*w[i]]+t*v[i]);
                    num[i]-=t;
                    t<<=1;
                }
                for(int j=V;j>=num[i]*w[i];--j) dp[j]=max(dp[j],dp[j-num[i]*w[i]]+num[i]*v[i]);
            }
        }
        //如果能抽取mid容量,则剩下的物品一定是完好且独立的
        if(dp[mid]>0){
            printf("Can be divided.\n\n");
        }
        else{
            printf("Can't be divided.\n\n");
        }
    }
    return 0;
}
View Code

hdu2546扣出一部分容量贪心

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005;
const int INF=~0u>>1;
int w[maxn],v[maxn],dp[maxn];
int main(){
    int N;
    while(~scanf("%d",&N)){
        if(!N) break;
        for(int i=0;i<N;++i){
            scanf("%d",&w[i]);v[i]=w[i];
        }
        int m;scanf("%d",&m);
        sort(w,w+N);sort(v,v+N);
        if(m<5){
            printf("%d\n",m);continue;
        }
        //买了x的最少剩余
        //把5和最贵的菜抠出来
        for(int i=0;i<maxn;++i) dp[i]=INF;dp[0]=m-5;
        for(int i=0;i<N-1;++i){
            for(int j=m-5;j>=w[i];--j) dp[j]=min(dp[j],dp[j-w[i]]-v[i]);
        }
        int ans=INF;
        for(int i=0;i<=m-5;++i) ans=min(ans,dp[i]);
        printf("%d\n",ans+5-v[N-1]);
    }
    return 0;
}
View Code

hdu1114完全背包

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=505;
const int INF=1e9;
int w[maxn],v[maxn],dp[10005];
int main(){
    int a;++  a;
    int T;scanf("%d",&T);
    while(T--){
        int E,F,N;scanf("%d%d",&E,&F);
        int V=F-E;
        scanf("%d",&N);
        for(int i=0;i<N;++i){
            scanf("%d%d",&v[i],&w[i]);
        }
        for(int i=0;i<=V;++i) dp[i]=INF;dp[0]=0;
        for(int i=0;i<N;++i){
            for(int j=w[i];j<=V;++j) dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
        }
        if(dp[V]==INF) printf("This is impossible.\n");
        else{
            printf("The minimum amount of money in the piggy-bank is %d.\n",dp[V]);
        }
    }
    return 0;
}
View Code

hdu2191多重背包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=105;
int w[maxn],v[maxn],num[maxn],dp[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        int n,m;scanf("%d%d",&n,&m);
        int V=n;
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&w[i],&v[i],&num[i]);
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<m;++i){
            if(num[i]*w[i]>V) for(int j=w[i];j<=V;++j) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            else{
                int t=1;
                while(t<num[i]){
                    for(int j=V;j>=t*w[i];--j) dp[j]=max(dp[j],dp[j-t*w[i]]+t*v[i]);
                    num[i]-=t;
                    t<<=1;
                }
                for(int j=V;j>=num[i]*w[i];--j) dp[j]=max(dp[j],dp[j-num[i]*w[i]]+num[i]*v[i]);
            }
        }
        printf("%d\n",dp[V]);
    }
    return 0;
}
View Code

hdu2602-01背包

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005;
int w[maxn],v[maxn],dp[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        int N,V;scanf("%d%d",&N,&V);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<N;++i){
            scanf("%d",&v[i]);
        }
        for(int i=0;i<N;++i){
            scanf("%d",&w[i]);
        }
        for(int i=0;i<N;++i){
            for(int j=V;j>=w[i];--j) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        }
        printf("%d\n",dp[V]);
    }
    return 0;
}
View Code

 

posted @ 2017-05-02 16:40  狡啮之仰  阅读(204)  评论(0编辑  收藏  举报