0/1背包问题 动态规划法

动态规划法:Dynamic Programming,DP
就像分治法一样可以将问题分为若干个子问题,但是呢,用动规法处理的子问题往往不是独立的,也就是说,子问题之间有相互联系,会相互影响的,参考Fibonacci数列,子问题之间是有联系的。

一般来说,子问题的重叠关系体现在给定问题满足的递推关系中(称谓动态规划函数)

通常来说,动态规划法将每个子问题求解一次并将其保存在一个表格中,当程序需要调用这些数据处理子问题时,只是简单通过查表获得该问题的解,从而避免了算了一次又算了一次。
因为把数据存起来了,就更加方便了。

0/1背包问题:
给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 w,其价值为 v 。
问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?

 

首先我们来滤清一下思路:
在对该问题的解决中,
该问题有两种潜在状态:
1.
背包容量不足以装入物品,背包不增加价值
2.

背包容量可以装下物品,背包的价值增加了。

第二个潜在状态:
也会出现两种分状态:
1.把第i个物品放入背包,背包的价值等于把前i-1个物品装入容量j-w(这个w指装入物体容量)获得的价值加上第i个物品的价值。
2.第i个物体的确可以装入背包,但我耍赖,不装,此时等于把i-1个物体装入背包获得的价值。

而要选最优解,当然要选两者中的最大值。

代码如下:
前缀:

#include<stdio.h>
#define N 10
#define Q 100 
int V[N+1][Q+1];
int KnapSack(int n,int w[],int v[],int C);

主函数:

int main()
{
 int w[N],v[N],C,maxValue;
 int n,i;
 printf("输入物体的个数:\n");
 scanf("%d",&n);
 printf("输入物体的重量:\n");
 for(i=0;i<n;i++)
  scanf("%d",&w[i]);
 printf("请输入物体的价值:\n");
 for(i=0;i<n;i++)
  scanf("%d",&v[i]);
  printf("请输入背包的容量:\n");
  scanf("%d",&C);
  maxValue=KnapSack(n,w,v,C);
  printf("获得的最大价值为:%d\n",maxValue);
 return 0;
 } 

函数:

 int KnapSack(int n,int w[],int v[],int C)
 {
  
  int i,j;
  for(j=0;j<=C;j++)
  V[0][j]=0;
  for(i=0;i<=n;i++)
  V[i][0]=0;
  for(i=1;i<=n;i++)
   for(j=1;j<=C;j++)
   {
    if(j<w[i-1])
    V[i][j]=V[i-1][j];
    else if(V[i-1][j]>V[i-1][j-w[i-1]]+v[i-1])
     V[i][j]=V[i-1][j];
     else
     V[i][j]=V[i-1][j-w[i-1]]+v[i-1];
     
   }
   
  return V[n][C];
 }

具体实验如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43504939/article/details/89892634
今日推荐