01背包

来源:互联网 发布:微商发图软件 编辑:程序博客网 时间:2024/04/29 07:51

01背包


背包有背包9讲,现在比较熟悉的就是01背包了,01背包的问题就是选或不选,那么用的就是动态规划(暂时还没有体验到这个特点。)
现在就来讲一讲:
01背包:
题目
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
基本思路
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
这个式子很重要,基本的思路就是这样。
1.二维:二维很方便,基本上就是一个二维VN数组,

长度 V 宽 N Phone $12 Pipe $1

代码如下:这里给出第一行开始填,也可以最后一行开始填

#include "stdafx.h"#include <iostream>#include <cstdio>#include <algorithm>using namespace std;struct  package{    int w;//价值    int v;//容量};int main(){    package bag[100];    int n, m;    int s[101][101];    cin >> n >> m;    for (int i = 0; i <= n; i++)        s[i][0] = 0;    for (int i = 0; i <= m; i++)        s[0][i] = 0;    //不知道为什么,一定要把上面的两个for语句写上,否则结果就会出现问题。    for (int i = 0; i < n; i++)    {        cin >> bag[i + 1].v >> bag[i + 1].w;    }    int d = min(bag[1].v, m);    for (int i = 0; i < d; i++)        s[1][i] = 0;    for (int i =d; i <= m; i++)        s[1][i] = bag[1].w;    for (int i = 2; i < n; i++)    {        for (int j = 0; j < bag[i].v; j++)            s[i][j] = s[i - 1][j];        for (int j = bag[i].v; j <= m; j++)            s[i][j] = max(s[i - 1][j], s[i - 1][j - bag[i].v] + bag[i].w);            //这里需要前面的初始化。当j=beg[i].v时,就是s[i-1][0]初始化。    }    if (bag[n].v > m)        s[n][m] = s[n - 1][m];    else        s[n][m] = max(s[n - 1][m], s[n - 1][m - bag[n].v] + bag[n].w);    printf("%d\n", s[n][m]);    system("pause");    return 0;}

上面的思路的是先将第一行填好,然后下一行根据上一行:
简单说就是:s[i]]n] 取决于s[i-1][n],和s[i-1][n-w]。
用过之后就就可以丢掉了,这就是为什么优化可以用一维来替换二维。
下面是一维代码:

//这里描述将二维压缩成一维背包#include "stdafx.h"#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;struct  package{    int w;    int v;};int main(){    package bag[1000];    int goal[1001];    int n, c;    cin >> n >> c;    for (int i = 1; i <= n; i++)    {        cin >> bag[i].w >> bag[i].v;    }    goal[0] = 0;//这里就相当于一维数组的初始化,将0行0列的初始化为0;    memset(goal, 0, sizeof(goal));    for (int i = 1; i <= n; i++)    {        for (int j = c; j >= bag[i].w; j--)            goal[j] = max(goal[j], goal[j - bag[i].w] + bag[i].v);    }    //这里分析为什么可以将二维压缩成一维,主要是将前面的s[i-1],[i]去掉了。    //同时必须要倒序,因为后面的数组的值是根据前面的s[j-w],s[j],如果正序    //就会先填s[j-w],导致错误    printf("%d\n", goal[c]);    system("pause");    return 0;}

用一维的过程和二维差不多,就是必须要倒序,原因如上。二维就是那种随便填的。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 衣服上的环生锈怎么办 黑暗之魂 中毒了怎么办 逗游下载速度慢怎么办 电推剪刀不锋利怎么办 白衣服洗得发黄怎么办 腰突然闪了很痛怎么办 一蹲下膝盖就疼怎么办 蹲久了膝盖疼怎么办 怀孕了外阴痒怎么办啊 我老婆出轨了我该怎么办 老婆有外遇我该怎么办 纸卡在打印机里怎么办 脸上的颧骨太高怎么办? 脸磕了一下淤血怎么办 腿磕到了有淤血怎么办 屁股摔了很疼怎么办 摔了脚踝肿了怎么办 扭了脚肿起来了怎么办 发际线低额头窄怎么办 档案写错了涂改怎么办 当时档案写错了怎么办 档案内容写错了怎么办 高中档案写错了怎么办 上大学档案丢了怎么办 u盘总提示格式化怎么办 黑莓手机id锁了怎么办 美图手机进水了怎么办 球兰叶子发黄软怎么办 蟹爪莲叶子发红怎么办 保险箱没电了打不开怎么办 宁波臭冬瓜酸的怎么办 甜酒酿做了酸了怎么办 孕妇喝了醪糟汤怎么办 鱼侧翻但又没死怎么办 原汁机盖子卡死怎么办 惠人原汁机坏了怎么办 泡芙鸡蛋加多了怎么办 淡奶油打过了怎么办 淡奶油打发过了怎么办 雷神锤子被捏碎怎么办 私处毛很多很黑怎么办