动态规划之背包问题

来源:互联网 发布:短信猫 java usb 编辑:程序博客网 时间:2024/06/06 00:12

动态规划之背包问题

问题:给定n个物品,每个物品都有重量和价值,现在希望选择一个物品子集使得总重量小于给定的重量并且总价值最大。问题如下图所示:
这里写图片描述
分析: 可以把问题的求解过程看成是一系列的决策过程,在第i步,我们决定i个物品是否装。现在假装我们得到子问题的最优解,当前考虑最后一个物品是装还是不装。如果装,则原问题变成从前n1个物品中选择限重WWn的物品子集使得价值最大。如果不装,则问题变成在前n1件物品中选择限重为W的物品子集使得价值最大。我们定义opt[i,w]为前i件物品中限重w的最大价值。此时,我们可以总结出递归表达式如下:

OPT[i,w]=maxOPT[i1,w],OPT[i1,wwi]+valuei

具体实现过程如下:

/*********************************************IDE:Dev c++5.11Data:2016.10.15Author:Robert.Tianyi**********************************************/#include<stdio.h>#include<stdlib.h>struct goods{    int price;    int w;};int max(int a,int b){    return a>b?a:b;}int Knapsack_DP(struct goods Goods[],int n){    int max_w=15;    int (*opt)[max_w+1];    int i,w,wi;    opt=(int (*)[max_w+1])malloc(sizeof(int)*(n+1)*(max_w+1));    for(i=0;i<=n;i++)        for(w=0;w<=max_w;w++)            opt[i][w]=0;    for(i=1;i<=n;i++){        for(w=1;w<=max_w;w++){            opt[i][w]=opt[i-1][w];            if(w-Goods[i].w>=0){               opt[i][w]=max( opt[i-1][w],opt[i-1][w-Goods[i].w]+Goods[i].price );                  }           }                       }    printf("最大重量:w ");    for(w=0;w<=max_w;w++)        printf("%4d",w);    printf("\n");    for(i=0;i<=n;i++){        printf("前%d件物品:",i);        for(w=0;w<=15;w++){           printf("%4d",opt[i][w]);                 }        printf("\n");    }    return opt[n][15];  }void main(){    int value;    struct goods Goods[6];    Goods[0].price=0;Goods[0].w=0;    Goods[1].price=10;Goods[1].w=9;    Goods[2].price=7;Goods[2].w=12;    Goods[3].price=1;Goods[3].w=2;    Goods[4].price=3;Goods[4].w=7;    Goods[5].price=2;Goods[5].w=5;    value=Knapsack_DP(Goods,5);    printf("max_price=%d",value);}

运行结果如下:
这里写图片描述
总结:本问题有nW个子问题,每个子问题做两次比较,所以时复杂度为O(nW)

0 0
原创粉丝点击