背包问题

问题描述:一个背包容量为V,有N件不同类别的物品体积和价值分别为:v[i], w[i],把这些物品装入背包中保证背包中物品的价值最高。背包问题分为以下几种:
一、0/1背包问题
1、算法描述:背包里的物品不能有重复,属于不同类别;
2、算法方程式:f[i][v] = max{f[i-1][v], f[i-1][v - c[i]] + w[i]};
3、算法举例:列(物品类别) 行(背包容量) 行列交叉得到背包内物品的价值
  0 1 2 3 4 5 6 7 8 9
0 0 0 3 3 3 3 3 3 3 3
1 0 0 3 4 4 7 7 7 7 7
2 0 0 3 4 5 7 8 9 9 12
3 0 0 3 4 5 7 8 10 11 12
4、源代码:
#include <stdio.h>
 
static int f[10] = {0};
static const int V = 9;
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
 
void ZeroOnePack(int cost, int weight)
{
      for(int v = V; v >= cost; -- v)
      {
            f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
      }
}
 
int main(int argc, char* argv[])
{
      for(int i = 0; i < n; ++ i)
      {
          ZeroOnePack(c[i], w[i]);
      }
      printf("%d", f[V]);
      return 0;
}
 
二、完全背包问题
1、算法描述:背包中属于同一类别物品可以重复,且每种类别物品数量不限;
2、算法方程式:f[i][v] = max{f[i-1][v], f[i-1][v - k * c[i]] + k * w[i]}(0=<k*c[i]<=V);
3、算法举例:
  0 1 2 3 4 5 6 7 8 9
0 0 0 3 3 6 6 9 9 12 12
1 0 0 3 4 6 7 9 10 12 13
2 0 0 3 4 6 7 9 10 12 13
3 0 0 3 4 6 7 9 10 12 13
4、源代码:
#include <stdio.h>
 
static int f[10] = {0};
static const int V = 9;
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
 
void CompletePack(int cost, int weight)
{
      for(int v = cost; v <= V; ++ v)
      {
            f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
      }
}
 
int main(int argc, char* argv[])
{
      for(int i = 0; i < n; ++ i)
      {
            CompletePack(c[i], w[i]);
      }
      printf("%d", f[V]);
      return 0;
}
 
三、多重背包问题
1、算法描述:背包中属于同一类别物品可以重复,但第i种物品数量最大量为n[i];
2、算法方程式:f[i][v]=max{f[i-1][v - k * c[i]] + k * w[i]}(0=<k<=n[i]);
3、源代码:
#include <stdio.h>
 
static int f[10] = {0};
static const int V = 9;
static const int n[4] = {2, 1, 1, 1};
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
 
//0/1背包解法
void ZeroOnePack(int cost, int weight)
{
      for(int v = V; v >= cost; -- v)
      {
            f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
      }
}
 
//完全背包解法
void CompletePack(int cost, int weight)
{
      for(int v = cost; v <= V; ++ v)
      {
            f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
      }
}
 
//多重背包解法
void MultiplePack(int cost, int weight, int amount)
{
      if(cost * amount >= V)
      {
            CompletePack(cost, weight);
            return ;
      }
 
      int k = 1;
      while(k < amount)
      {
            ZeroOnePack(k * cost, k * weight);
            amount -= k;
            k *= 2;
      }
 
      ZeroOnePack(amount * cost, amount * weight);
}
 
int main(int argc, char* argv[])
{
      for(int i = 0; i < 4; ++ i)
      {
            MultiplePack(c[i], w[i], n[i]);
      }
 
      printf("%d", f[V]);
      return 0;
}
原文地址:https://www.cnblogs.com/ourroad/p/3078942.html