动态规划 背包问题

1.问题描述

有n个物体有重量和价值两个属性,一个能承重一定重量的背包。问怎么选择物体能实现背包里的价值最大化。

2.问题具体化

假设有5个物体和一个背包。物体的重量分别是2、2、6、5、4,即w[]={0、2、2、6、5、4},价值分别是6、3、5、4、6,即v[]={0、6、3、5、4、6}。背包承重为10。问怎么选择,能实现背包所背物体价值的最大化。

3. 解决过程

利用二维表格,通过自左向右、自下向上的计算,来绘制表格,左后再在表格的基础上选择最优解。

  • 3.1表格最后一行

对最后一行的物体4来说,只有两种情况,要么装入背包,要么不装入。物体5的的重量是4。也就是说在背包承重为0--3的时候物体5是装不进去的,所以背包为0,当背包承重为4--10的时候,物体5可以装进去,又因为物体5的价值为6,所以背包价值为6。

|.|0|1|2|3|4|5|6|7|8|9|10|
|--
|1
|2
|3
|4|
|5|0|0|0|0|6|6|6|6|6|6|6|

  • 3.2表格倒数第二行

    表格倒数第二行的计算思路与倒数第一不一样,因为我们要考虑背包里已经有的物体。因为物体4的重量为5。所以在背包承重为0--4的情况下即使空包也装不进去,所以不能装入,包里原本是多少价值,就还是多少价值。在背包承重为5--8的时候,物体4可以装进去,但是物体5要拿出来才行,这样的话背包的价值就变成4了,小于6。所以能然选择不把物体4放进去。在背包承重为9--10的时候,两个都可以放进去,所以背包的价值变成10了。

|.|0|1|2|3|4|5|6|7|8|9|10|
|--
|1
|2
|3
|4|0|0|0|0|6|6|6|6|6|10|10|
|5|0|0|0|0|6|6|6|6|6|6|6|

  • 3.3最终计算出来的表格

其他行的计算过程同上,最终结果如下。

|.|0|1|2|3|4|5|6|7|8|9|10|
|--
|1|0|0|6|6|9|9|12|12|15|15|15|
|2|0|0|3|3|6|6|9|9|9|10|11|
|3|0|0|0|0|6|6|6|6|6|10|11|
|4|0|0|0|0|6|6|6|6|6|10|10|
|5|0|0|0|0|6|6|6|6|6|6|6|

  • 3.4表格计算公式

max( m(i+1,j) , m(i+1,j-wi)+vi )

  • 3.5做出最优选择

大体思想:我们从右上角(坐标(1,10))开始,看(1,10)与(2,10)的值是不是一样,一样,则说明物体1没装进去,不一样,则说明物体1装进去了。
void opt_way(int flag[],int w[], int table[num][weight])
{
int n = weight-1;
for (size_t i = 0; i < num; i++)
{
if (table[i][n]==table[i+1][n])
{
flag[i] = 0;
}
else
{
flag[i] = 1;
n = n - w[i+1];
}
}
}


4.完整代码

#include <iostream>
#define num 5
#define weight  11
using namespace std;

void init_table(int table[num][weight])
{
    for (size_t i = 0; i < num; i++)
    {
        for (size_t j = 0; j < weight; j++)
        {
            table[i][j] = 0;
        }
    }

}
void show_table(int table[num][weight])
{
    for (size_t i = 0; i < num; i++)
    {
        for (size_t j = 0; j < weight; j++)
        {
            cout <<table[i][j] << "\t";
        }
        cout << "\n";
    }

}
void creat_table(int table[num][weight],int w[],int v[])
{
    //给最后一行赋初值
    for (size_t i = 0; i < weight; i++)
    {
        if (w[num] > i)
            table[num - 1][i] = 0;
        else
        {
            table[num - 1][i] = v[num];
        }
    }
    //在最后一行基础上给每行赋值
    for (int i = num - 1; i > 0; i--)
    {
        for (int j = 0; j < weight; j++)
        {
            if (w[i]>j)
            {
                table[i - 1][j] = table[i][j];
            }
            else if ((v[i] + table[i][j-w[i]])>table[i][j])
            {
                table[i-1][j] = v[i] + table[i ][j - w[i]];
            }
            else
            {
                table[i-1][j] = table[i][j];
            }
        }
    }

}



void opt_way(int flag[],int w[], int table[num][weight])
{
    int n = weight-1;
    for (size_t i = 0; i < num; i++)
    {
        if (table[i][n]==table[i+1][n])
        {
            flag[i] = 0;
        }
        else
        {
            flag[i] = 1;
            n = n - w[i+1];
        }
    }

}
int main()
{
    int w[num+1] = {0,2,2,6,5,4};
    int  v[num+1]= {0,6,3,5,4,6};
    int flag[num] = { 0, 0, 0, 0, 0 };
    int table[num][weight];
    init_table(table);
    creat_table(table,w,v);
    opt_way(flag,w,table);
    //----------------
    show_table(table);
    //------------------------------
    for (size_t i = 0; i < num; i++)
    {
        cout << flag[i];
    }
    getchar();
    return 0;
}

5.程序结果截图

11001是最优的选择
11001是最优的选择
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容

  • 本篇博文参考此博文,该博文PPT非常有助理解 问题描述:给定n种物品和一背包。物品i的重量是wi,其价值为vi,背...
    icecrea阅读 1,487评论 0 4
  • 动态规划 之 0-1背包问题 【背包问题】 现有n个物品,价值为`$$v_1,v_2....v_n$$ 重量为 现...
    siriusing阅读 230评论 0 0
  • 前几天钱包的卡扣坏了,当时就想到换钱包的念头,是时候该给钱换个舒服的家了。隐约记得在哪里看过,说用钱包最好用长的,...
    糖小炜阅读 308评论 0 0
  • 健康并不是被创造出来的,它或者被疾病隐藏起来,或者当没有病的时候它自己就显露出来了。健康己经在我们里面,健...
    婉缘阅读 289评论 0 0
  • 夏天披萨 和 时光铺子的酒
    Kodel阅读 160评论 0 0