算法程序设计 之 背包问题(5/8)

一、实验目的:

理解并掌握利用-动态规划算法与贪心算法求解不同背包问题。

  • 实验内容
  1. 0-1背包问题

给定n种物品和一个背包。物品i的重量是w[i],其价值为vi,背包的容量为C。问如何选择装入背包的物品,使得装入背包中物品的总价值最大?

在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。不能将物品装入背包多次,也不能只装入部分的物品,因此称之为0-1背包问题。

2. 小数背包问题

给定n种物品和一个背包。物品i的重量是w[i],其价值为vi,背包的容量为C。问如何选择装入背包的物品,使得装入背包中物品的总价值最大?

在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包。

程序代码:

  1. 0-1背包问题:

#include <iostream>

#include <string>

using namespace std;

const int N = 150;//定义全局变量使N值不变

int max(int a, int b);

int v[N]; //价值数组

int w[N]; //重量数组

int n, c; //n个数,c容量

int i, j;

int recursion()

{  int V[N][N]; //建立一个二维数组,v(i,j)中i表示考虑第i到第n个物品,j表示当前容量

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

        V[i][0] = 0;

    for (j = 0; j <= c; j++)

        V[0][j] = 0;

    //计算第i行,进行第i次迭代

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

    {

        for (j = 1; j <= c; j++)

        {

            if (j < w[i])//此时背包剩余容量小于第i个物品所以不装第i个物品,便成立考虑 第i-1到第n个物品

                V[i][j] = V[i - 1][j];

            else

                V[i][j] = max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);

//V[i - 1][j]表示没有装第i个物品, V[i - 1][j - w[i]] + v[i] 表示装了第i个物品再考虑考虑第i-1到第n个物品

        } }

    j = c;

    cout << "装入的物品:";

    for (i = n; i > 0; i--)

    {  if (V[i][j] > V[i - 1][j])//前者价值大于后者说明装了第i个物品

        {   cout << "\n";

        cout << "装入第" << i << "个物品";

           j = j - w[i];

        continue;

        }

        else

             cout << "\n";

                cout << "不装入第" << i << "个物品";

    }

    return V[n][c];

}

int max(int a, int b)

{

    if (a >= b)

        return a;

    else

        return b;

}

int input()

{  

cout << "请输入物品的个数: ";

   cin >> n;

    cout << "请输入背包的容量: ";

    cin >> c;

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

    {

        cout << "请输入第" << i << "个物品的质量: ";

        cin >> w[i];

    }

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

    {

        cout << "输入第" << j << "个物品的价值: ";

        cin >> v[j];

    }

}

int main()

{

    input();

    cout << "最大价值为:" << recursion() << endl;

    return 0;

}

  1. 小数背包问题:

#include <iostream>

#include <string>

using namespace std;

const int N = 150;

int max(float p[N], int n)

{

 float max = p[0];

 int maxi = 0;

 for (int i = 0; i < n; i++)

  {

  if (p[i] > max) {

  max = p[i];

   maxi = i;

  }

 }

 p[maxi] = 0;

 return maxi;

}

void traceback(int n, int c, int w[N], int v[N]) {

 float p[N];//价值权重

 int i;

 int weight = 0;float value = 0;//总重量,总价值

 for (i = 0; i < n; i++) //权重计算

  p[i] = v[i] / (w[i]*1.0);

 for (i = 0; i < n; i++) {

  int num = max(p, n);//价值最高的下标

  weight += w[num];

  if (weight < c) {

   cout << "装入物品" << i+1 << "的重量为 " << w[num] << "  价值为 " << v[num] << " 完整装入" << endl;

   value += v[num];

  }

  else if (weight > c) {

   float w1 = (c - (weight- w[num])) /( w[num]*1.0);//计算装入部分

   cout << "装入物品" << i+1 << "的重量为 " << w[num] << "  价值为 " << v[num] << " 装入百分之" << w1*100 << endl;

   weight = c;

   value += w1 * v[num];

  }

  else break;

 }

 cout << "装入的总重量为 " << weight << endl;

 cout << "装入的总价值为 " << value << endl;

}

int main()

{

int v[N];

 int w[N];

 int n, c;

 cout << "请输入物品的个数: ";

 cin >> n;

 cout << "请输入背包的容量: ";

 cin >> c;

 int i, j;

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

 {

  cout << "请输入第" << i + 1 << "个物品的质量: ";

  cin >> w[i];

 }

 for (j = 0; j < n; j++)

 {

  cout << "输入第" << j + 1 << "个物品的价值: ";

  cin >> v[j];

 }

 traceback(n, c, w, v);

 return 0;

}

程序测试及运行结果:

01

 

小数:

分析与讨论:


0-1背包问题是一个特殊的整数规划问题

     设是所给0-1背包问题的一个最优解,则是下面相应子问题的一个最优解

     设子问题的最优值为其中是背包容量为,可选择物品为时0-1背包问题的最优值,就可以得到递推公式。

 小数背包问题运用贪心算法

        其算法与0-1背包大体相似,贪心算法解决小数背包问题与0-1背包的整数规划问题最大的不同小数背包问题需要算出每个物品的权重,通过比较权重大小,来判断放入背包的顺序,直到背包放满。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

君无戏言。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值