《算法设计与分析》实验报告(五)之背包问题

文章讲述了0-1背包问题和小数背包问题的解决方法,通过动态规划求解0-1背包问题,以及利用贪心算法处理小数背包问题,强调了动态规划的最优子结构性质和贪心算法的局部最优策略。
摘要由CSDN通过智能技术生成
  • 实验内容
  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;

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

int max(int a, int b);

int main()

{

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

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

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

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

    cin >> n;

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

    cin >> c;



    int i, j;

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

    {

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

        cin >> w[i];

    }

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

    {

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

        cin >> v[j];

    }

    cout << "最大价值:" << traceback(n, c, w, v) << endl;

    return 0;

}

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

{

    int V[N][N];

    int i, 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])

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

            else

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

        }

    }

    //装入物品

    int x[N];

    j = c;

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

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

    {

        if (V[i][j] > V[i - 1][j])

        {

            x[i] = 1;

            j = j - w[i];

        }

        else

            x[i] = 0;

    }

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

        cout << x[i] << '\t';

    cout << endl;

    return V[n][c];

}

int max(int a, int b)

{

    if (a >= b)

        return a;

    else

        return b;

}

2.小数背包

#include <iostream>

#include <string>

using namespace std;

const int N = 150;

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

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

int main()

{

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

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

    int n, c; //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;

}

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 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;

}

程序测试及运行结果:

1.0-1背包

2.小数背包

分析与讨论:

动态规划方法的原理就是把多阶段决策过程转化为一系列的单阶段决策问题,利用各个阶段之间的递推关系,逐个确定每个阶段的最优化决策,最终堆叠出多阶段决策的最优化决策结果。。

0-1背包问题具有最优子结构性质,所以可以用动态规划方法求解。根据这种性质定义递归关系并建立递归方程,以自底向上的方式计算最优值。而且以后编程时要彻底理解问题后再构造算法。

贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。

贪心算法是按照各种量度标准排序物品。对于每一种排序结果,在背包容量内,选择量度最大的物品,继续选择次量度最大的物品,直到选到当前量度最大物品的重量大于背包剩余容量时(容不下),放入物品的一部分,这部分和背包剩余容量相等。打印出各物品是否被选择,或者被选择的比例。

贪心选择性质:所求问题的全局最优解可以通过一系列局部最优的选择(即贪心选择)来达到。
 

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
目录: 实验一 递归与分析...............................................01 1.实验内容....................................................01 2.实验目的....................................................01 3.程序清单....................................................01 (1)循环赛日程安排..........................................01 (2)最近点对核心代码........................................04 4.实验结果....................................................06 5.分析与思考..................................................06 实验二 动态规划.................................................09 1.实验内容....................................................09 2.实验目的....................................................09 3.程序清单....................................................09 (1)TSP问题核心代码.................................................09 (2)0-1背包问题核心代码........................................11 4.实验结果....................................................13 5.分析与思考..................................................13 实验三 贪心算法.................................................16 1.实验内容....................................................16 2.实验目的....................................................16 3.程序清单....................................................16 (1)最近邻点策略解决TSP问题.................................16 (2)多机调度问题............................................17 4.实验结果....................................................18 5.分析与思考..................................................19 实验三 回溯法...................................................21 1.实验内容....................................................21 2.实验目的....................................................21 3.程序清单....................................................21 (1)求解0-1背包问题........................................21 (2)求解TSP问题............................................22 4.实验结果....................................................23 5.分析与思考..................................................24 附录: 实验二表格绘制案例说明(无监视器)...............................25 各实验题目描述
01背包问题是一个经典的动态规划问题,通常涉及到在给定的一组物品中选择一些物品,使得它们的总体积不超过背包的容量,同时总体积最大化。针对这个问题,可能会遇到以下几个问题: 1.如何建立状态转移方程? 状态转移方程是解决动态规划问题的核心。对于01背包问题,可以使用以下状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])。其中,dp[i][j]表示前i个物品放入容量为j的背包中所能获得的最大价值,w[i]和v[i]分别表示第i个物品的重量和价值。在状态转移方程中,如果第i个物品的重量大于当前背包容量j,则无法放入,此时的最大价值就是前i-1个物品放入容量为j的背包中所能获得的最大价值;否则,第i个物品可以放入背包中,此时的最大价值就是前i-1个物品放入容量为j-w[i]的背包中所能获得的最大价值加上第i个物品的价值v[i]。 2.如何处理边界条件? 在状态转移方程中,需要处理边界条件。对于01背包问题,可以将dp数组的第0行和第0列都初始化为0,表示背包容量为0或者没有物品可选时,最大价值都为0。 3.如何优化空间复杂度? dp数组的大小与物品数量和背包容量有关,因此可能会导致空间复杂度较高。为了优化空间复杂度,可以使用滚动数组或者状态压缩的方法。 4.如何输出具体方案? 在求解最大价值的同时,可以记录下哪些物品被选中,从而输出具体的方案。可以在状态转移方程中添加一个二维数组path,用于记录选中的物品。当dp[i][j]由dp[i-1][j]转移而来时,说明第i个物品没有被选中;当dp[i][j]由dp[i-1][j-w[i]]+v[i]转移而来时,说明第i个物品被选中。最后,通过反向遍历path数组,可以得到具体的方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

了一li

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

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

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

打赏作者

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

抵扣说明:

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

余额充值