01背包问题(动态规划)

    xiaoxiao2023-03-24  5

    01背包问题

    问题描述:在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1W2……Wn,与之相对应的价值为P1,P2……Pn

    解决方案:动态规划。为什么不能用贪心?贪心虽然会带来每一次最优但是不一定是整体最优。(比如说C的性价比最高,但是放了C就不能放别的了,总价值就不如放A和B的多了)

    【题目名称】0/1背包

    一个旅行者有一个最多能装m公斤物品的背包,现在有n件物品,它们的重量分别是w1,w2,…,wn,它们的价值分别为c1,c2,…,cn。若每一种物品只有一件,求旅行者能获得的最大总价值。

    【输入格式】 第一行:两个整数,m(背包容量,m<=200)和n(物品数量,n<=30)。

    第二~n+1行:每行两个整数wi,ci,表示每个物品的重量和价值

    【输出格式】 一个数据,表示最大总价值

    【输入样例#1】

    10 4

    2 1

    3 3

    4 5

    7 9

    【输出样例#1】 12

    【题目分析】

    01背包就是意味着每个物品只有一种,可以选择放或者不放。,因此,为了让背包的价值最高,就是要将前i件物品放入一个容量为m的背包来获得最大的价值。

    按照这种实现思想,实现的思路如下:

    (1)  分析将前i件物品放入容量为m的背包这个问题,将其转化为一个只牵扯前i-1件物品的问题。

    a.  如果不放第i件物品,就可以将问题转化为“前i-1件物品放入容量为m的背包”;然后重复之前的过程

    b.  如果放第i件物品,就可以将问题转化为“前i-1件物品放入剩下容量为m-w[i]的背包”,此时能获得的最大价值就 是f[i-1,m-w[i]]+v[i].

    (2)  根据上述分析,得出状态转移方程:f[i,v]=max{f[i-1,m],f[i-1,m-w[i]]+v[i]};

    (3)  由于状态方程,需要一个名为max的函数来比较两个数的较大者;

    (4)  输出背包的最大价值

    【C代码】

    #include <stdio.h>

    int max(int x,int y){        //求x和y的最大值

        if(x>y)

           return x;

        else

           return y;

    }

    int main(){

         int m,n,x,i;             //定义变量

         int w[30],v[30];

         int f[30][200];

         scanf("%d%d",&m,&n);   //读入背包容量m和物品数量n

         for(i=1;i<=n;i++)

            scanf("%d %d",&w[i],&v[i]);

       

         for(i=1;i<=n;i++){     //f(i,x)表示前i件物品,总重量不超过x的最优价值

            for(x=1;x<=m;x++){

               if(x>=w[i])

                   f[i][x]=max(f[i-1][x-w[i]]+v[i],f[i-1][x]);

               else f[i][x]=f[i-1][x];

            }

         }

         printf("%d\n",f[n][m]);   //f[n][m]为最优解

         return 0;

    }

    【PASCAL代码】

    const

      maxm=200 ;  maxn =30;   //背包容量<=200,物品数量<=30

    var

      m,n,x,i:integer;

      v,w:array[1..maxn] of integer;

      f:array[0..maxn,0..maxm] of integer;

     

    functionmax(x,y:integer) :integer;  //求x和y的最大值

    begin

      if x>y then max:=x else max:=y;

    end;

     

    begin

      readln(m,n);            //读入背包容量m和物品数量n

      for i:=1 to n do

        readln(w[i],v[i]);    //读入每个物品的重量和价值

     

      for i:=1 to n do

        for x:=1 to m do

          begin               //f(i,x)表示前i件物品,总重量不超过x的最优价值

            if x>=w[i] then f[i,x]:=max(f[i-1,x-w[i]]+v[i],f[i-1,x])

            else f[i,x]:=f[i-1,x];

          end;

      writeln(f[n,m]);        //f(n,m)为最优解

    end.

    转载请注明原文地址: https://ju.6miu.com/read-1200958.html
    最新回复(0)