01背包问题(动态规划)

7 篇文章 0 订阅

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.








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 我们来看一下01背包问题的代码:def knapsack01(items, n, W): # 初始化动态规划表 dp = [[0 for x in range(W + 1)] for x in range(n + 1)] # 构建动态规划表 for i in range(1, n + 1): for w in range(1, W + 1): if items[i-1][1] <= w: dp[i][w] = max(items[i-1][0] + dp[i-1][w-items[i-1][1]], dp[i-1][w]) else: dp[i][w] = dp[i-1][w] return dp[n][W] # 例子 items = [[60, 10], [100, 20], [120, 30]] n = len(items) W = 50 print(knapsack01(items, n, W)) ### 回答2: 下面是一个用动态规划解决01背包问题的代码: ```python def knapsack(weight, value, capacity): # 初始化一个二维数组来保存最大价值 dp = [[0] * (capacity + 1) for _ in range(len(weight) + 1)] for i in range(1, len(weight) + 1): for j in range(1, capacity + 1): # 如果当前物品的重量小于等于背包容量 if weight[i - 1] <= j: # 当前状态的最大价值为两种情况的最大值 # 1. 不放入当前物品,即前一个状态的最大价值 # 2. 放入当前物品,即剩余容量背包的最大价值 + 当前物品的价值 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]) else: # 当前物品的重量大于背包容量,不放入当前物品 dp[i][j] = dp[i - 1][j] # 返回最终状态的最大价值 return dp[len(weight)][capacity] # 测试代码 weight = [2, 3, 4, 5] # 物品的重量 value = [3, 4, 5, 6] # 物品的价值 capacity = 8 # 背包的容量 result = knapsack(weight, value, capacity) print("最大价值:", result) ``` 这个代码使用了动态规划的思想,通过一个二维数组`dp`保存每个状态下的最大价值。通过遍历物品和背包容量来更新`dp`数组,最终得到最大价值。 ### 回答3: 01背包问题是一个经典的动态规划问题,题目要求在一个给定的背包容量下,选择若干个物品装入背包,使得物品的总价值最大化,每个物品只能选择放入一次。 下面是一个简单的实现01背包问题的代码: ```python def knapSack(W, wt, val, n): # 创建一个二维数组来保存子问题的最优解 dp = [[0 for x in range(W+1)] for x in range(n+1)] # 填充dp数组,计算子问题的最优解 for i in range(n+1): for w in range(W+1): if i == 0 or w == 0: dp[i][w] = 0 elif wt[i-1] <= w: dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]) else: dp[i][w] = dp[i-1][w] return dp[n][W] # 测试案例 val = [60, 100, 120] wt = [10, 20, 30] W = 50 n = len(val) print(knapSack(W, wt, val, n)) ``` 上述代码中,我们使用了一个二维数组dp来保存子问题的最优解。其中dp[i][w]表示前i个物品中,在背包容量为w的情况下,能够达到的最优解。初始时,dp数组全为0。然后我们使用两层循环,依次计算并填充dp数组。 最后返回dp[n][W]即为问题的最优解。 在上述代码中,我们给出了一个测试案例。该测试案例中,我们有3个物品,其重量分别为10、20和30,对应的价值分别为60、100和120。背包的容量为50。最终程序输出的结果为220,即在背包容量为50的情况下,我们选择前两个物品,能够达到的最大总价值为220。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

【ACGO】我不会C++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值