背包问题

来源:互联网 发布:华夏银行贵金属软件 编辑:程序博客网 时间:2024/05/16 07:48

首先是0-1背包问题,这是最基本的背包问题,给定一个背包,容量为V,给定n个物品,并给出每个物品的体积和价值,每个物体只有一件。

下面是0-1背包问题的代码模型:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 110#define Maxv 1010#define Maxx(a,b) (a)>(b)?(a):(b)int weight[Max];int value[Max];int dp[Maxv];int V;int n;int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d%d",&weight[i],&value[i]);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++)for(int j=V;j>=weight[i];j--)dp[j]=Maxx(dp[j],dp[j-weight[i]]+value[i]);        printf("%d\n",dp[V]);return 0;}

完全背包问题:
区别与0-1背包问题的关键点是:物体的个数是无穷,下面是代码模型:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 110#define Maxv 1010#define Maxx(a,b) (a)>(b)?(a):(b)#define Inf 11111100int weight[Max];int value[Max];int dp[Maxv];int V;int n;int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d%d",&weight[i],&value[i]);memset(dp,0,sizeof(dp));//要求刚好装满//for(int i=1;i<=V;i++)//dp[i]=-Inf;//dp[0]=0;for(int i=1;i<=n;i++)for(int j=weight[i];j<=V;j++)dp[j]=Maxx(dp[j],dp[j-weight[i]]+value[i]);printf("%d\n",dp[V]);return 0;}

多重背包问题:

区别于0-1背包问题的关键在于物体的个数为num[i]下面是没有优化的代码模型

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 110#define Maxv 1010#define Maxx(a,b) (a)>(b)?(a):(b)#define Inf 11111100int weight[Max];int value[Max];int num[Max];int dp[Maxv];int V;int n;int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d%d%d",&weight[i],&value[i],&num[i]);memset(dp,0,sizeof(dp));//要求刚好装满//for(int i=1;i<=V;i++)//dp[i]=-Inf;//dp[0]=0;for(int i=1;i<=n;i++)for(int k=0;k<=num[i];k++)  for(int j=V;j>=weight[i];j--)dp[j]=Maxx(dp[j],dp[j-weight[i]]+value[i]);printf("%d\n",dp[V]);return 0;}
以hdu2191为例说明:
下面是优化代码一:
#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max(a,b) (a)>(b)?(a):(b)#define Maxv 110#define Maxx 20010int V,n,Case;int dp[Maxv];int weight[Maxx];int value[Maxx];int main(){    scanf("%d",&Case);    while(Case--){        scanf("%d%d",&V,&n);        memset(dp,0,sizeof(dp));        int pivot=0;        int ww,vv,nn;        for(int i=1;i<=n;i++){            scanf("%d%d%d",&ww,&vv,&nn);            for(int j=1;j<nn;j<<=1){                weight[pivot]=j*ww;                value[pivot++]=j*vv;                nn-=j;            }            weight[pivot]=nn*ww;            value[pivot++]=nn*vv;        }        for(int i=0;i<pivot;i++)            for(int j=V;j>=weight[i];j--)                dp[j]=Max(dp[j],dp[j-weight[i]]+value[i]);        printf("%d\n",dp[V]);    }    return 0;}

 

下面是优化代码二:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Maxv 110#define Max(a,b) (a)>(b)?(a):(b)int dp[Maxv];int n,V,Case;int ww,vv,nn;void onepage(int weight,int value){    for(int i=V;i>=weight;i--)        dp[i]=Max(dp[i],dp[i-weight]+value);}void compage(int weight,int value){    for(int i=weight;i<=V;i++)        dp[i]=Max(dp[i],dp[i-weight]+value);}int main(){    scanf("%d",&Case);    while(Case--){        scanf("%d%d",&V,&n);        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;i++){           scanf("%d%d%d",&ww,&vv,&nn);           if(ww*nn>=V)               compage(ww,vv);           else{               for(int j=1;j<nn;j<<=1){                   onepage(ww*j,vv*j);                   nn-=j;               }               onepage(nn*ww,nn*vv);           }        }        printf("%d\n",dp[V]);    }    return 0;}

背包问题的核心是0-1背包问题的动态转移方程。dp[v]=max{dp[v],dp[v-weight]+value}

另外就是注意初始化问题。

                                             
0 0
原创粉丝点击