文章目录

  • 一、算法要求
    • 1. 思路
    • 2. 示例
  • 二、完整代码
    • 1. 主文件
    • 2. 头文件
    • 3. 效果展示
  • 三、补充

一、算法要求

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

1. 思路

有n种可选物品1,…,n ,放入容量为c的背包内,使装入的物品具有最大效益。

n :物品个数
c :背包容量
p1,p2, …, pn:个体物品效益值
w1,w2, …,wn:个体物品容量

0-1背包问题的解法:物品1,…,n的一种放法(x1, ···,xn的0/1赋值),使得效益值最大。
假定背包容量不足以装入所有物品:面临选择

优化原理:无论优化解是否放物品1,优化解对物品2,…,n的放法,相对剩余背包容量,也是优化解。

2. 示例

假设:n=5,c=10p=[6,3,5,4,6]w=[2,2,6,5,4]


(1,1,0,0,1)为其优化解,即放物品1,2,5 。物品1占背包容量2,剩下容量为8。

考虑子问题:n=4,c=8,物品为2,3,4,5
(1,0,0,1),即放物品2和5,是子问题的优化解,背包问题满足优化原理。


二、完整代码

1. 主文件

main.cpp:

#include"Improve1.h"int main(){//初始化控制台Console();//核心算法CoreAlgorithm();// 输出cout << "\nThe maximum total value of the items in the backpack is:" << m[1][capacityPack] << endl;cout << "The selected item situation is:";for (int i = 1; i <= numItem; i++)cout << x[i] << " ";cout << endl;return 0;
}

2. 头文件

Improve1.h:

#pragma once#ifndef __IMPROVE1__
#define __IMPROVE1__#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
using namespace std;/*n :物品个数*c :背包容量*p1,p2, …, pn:个体物品效益值*w1,w2, …,wn:个体物品容量*/int numItem = 5,capacityPack = 10;
int weightItem[] = { 0, 2, 2, 6, 5, 4 },   //从第一序列开始valueItem[] = { 0, 6, 3, 5, 4, 6 };
int* x;     // 物品是否被放入背包
int** m;    // 最大价值// 用户输入
void Console() {cout << "The following are the default items’ quantity, value and weight and backpack capacity: \n"<< "\n#Number of items: " << numItem<< "\n#Number of backpacks: " << capacityPack;cout << "\n#Corresponding weight: ";for (int i = 1; i < numItem + 1; i++)cout << setw(3) << weightItem[i];cout << "\n#Corresponding value: ";for (int i = 1; i < numItem + 1; i++)cout << setw(3) << valueItem[i];x = new int[numItem + 1];m = new int* [numItem + 1];for (int i = 0; i <= numItem; i++) {m[i] = new int[capacityPack + 1];memset(m[i], 0, sizeof(int) * (capacityPack + 1)); // 将表m所有元素设为0}cout << endl;}//核心算法
void CoreAlgorithm(){//Knapsack最大价值表int jMax = min(weightItem[numItem] - 1, capacityPack);     // 避免存在单个重量超出背包容量的物品使数组m越界for (int j = 0; j <= jMax; j++)            // 以下两个for循环是最大价值表m的最后一行m[numItem][j] = 0;for (int j = weightItem[numItem]; j <= capacityPack; j++)m[numItem][j] = valueItem[numItem];for (int i = numItem - 1; i > 1; i--) {  // 以下是表m最后一行以上的部分jMax = min(weightItem[i] - 1, capacityPack);for (int j = 0; j <= jMax; j++)// 背包容量<物品重量,即装不下;将m[i+1][j](下一行同列)的值赋给m[i][j]m[i][j] = m[i + 1][j];for (int j = weightItem[i]; j <= capacityPack; j++)// 背包容量>=物品重量,即可以装下;//        放:m[i][j]=m[i + 1][j - w[i]] + v[i]//     不放:m[i][j]=m[i + 1][j]// 哪个价值大,就采取哪种方式m[i][j] = max(m[i + 1][j], m[i + 1][j - weightItem[i]] + valueItem[i]);}m[1][capacityPack] = m[2][capacityPack];if (capacityPack >= weightItem[1])m[1][capacityPack] = max(m[1][capacityPack], m[2][capacityPack - weightItem[1]] + valueItem[1]);//Traceback将最优解存入数组int cTemp = capacityPack;    // 临时背包容量for (int i = 1; i < numItem; i++) {if (m[i][cTemp] == m[i + 1][cTemp])x[i] = 0;  // 价值相等,说明没有放入这个物品,0else {x[i] = 1;  // 价值不相等,说明放入了这个物品,1cTemp -= weightItem[i];  // 放入了一个物品,背包剩余容量为原容量-物品重量}}x[numItem] = (m[numItem][capacityPack]) ? 1 : 0;    // 最后一个物品,非0为true放入,0为false不放入
}#endif

3. 效果展示


三、补充

优化值间的递归式:
虽然不知道优化解是否放物品1,但从优化原理能建立优化值间的递归式:
设f(i, y)为以背包容量y,放物品i,…,n,得到的优化效益值,以下递归关系成立:

f(1,c)=max{f(2,c), f(2,c-w1)+p1}  不放物品1、放物品1
先求子问题的优化值(递归),再从2种可能性中求出最优的。

须对任意给定容量y,任意i,…,n 种物品求解子问题。

举例:

n=3, c=116
w=[100,14,10]
p=[20,18,15]
放进物品1(x1 = 1),背包容量还剩r=16, [x2,x3]= [1,0] 为子问题的优化解,值为18,总效益值为20+18=38
不放物品1(x1= 0)则对于剩下的两种物品而言,容量限制条件为116,[1,1]为子问题优化解,值为33。
前者效益值为38,后者为33;
所以优化解为[1,1,0], 优化值为max{38,33}=38。
  1. 算法复杂度分析:
    (1)时间复杂度:算法中有主要的是两层嵌套的for循环,其时间复杂度为O(n×w)。
    (2)空间复杂度:由于二维数组c[n][w],所以空间复杂度为O(n×w)。
  2. 算法优化拓展:
    首先有一个主循环i=1,2,…,N,每次算出来二维数组c[i][0~w]的所有值。那么,如果只用一个数组 dp[0~w],能不能保证第i次循环结束后dp[i]中表示的就是我们定义的状态 c[i][j]呢?
    c[i]]由c[i-1][i]和c[i-1] [j-w[i]]两个子问题递推而来,能否保证在递推 c[i][i]时(也即在第i次主循环中递推 dp[j]时)能够得到c[i-1][j]和c[i-1][j-w[i]]的值呢﹖事实上,这要求在每次主循环中以j=w,w-1,…,1,0的顺序倒推dp[j],这样才能保证递推 dp[j]时dp[j-c[i]]保存的是状态c[i-1][j-w[i]]的值。

伪代码如下:

 for i=1..nfor j=w..0dp [j]=max{dp[j] ,dp [j-w[i]]+v[i]};
其中,dp[j]=max {dp[j],dp[j-w[i]]}就相当于转移方程c[i][j]-max {c[i-1][j],c[i-1][j-w[i]]},
因为这里的dp[j-w[i]] 就相当于原来的c[i-1][j-w[i]]。

文档供本人学习笔记使用,仅供参考。

【0-1背包问题】“动态规划”——《算法设计与分析(第五版)》相关推荐

  1. 计算机算法设计与分析第五章思维导图知识点总结 ( 初稿 )

    复习链接 计算机算法设计与分析第一章思维导图 计算机算法设计与分析第二章思维导图&&知识点总结 计算机算法设计与分析第三章思维导图&&知识点总结 计算机算法设计与分析第 ...

  2. PHP第五周答案,算法设计与分析第五周作业——Word Ladder

    算法设计与分析第五周作业--Word Ladder 上周找了一道深度搜索优先搜索的算法题来做,于是这周就选了一道广度优先搜索算法题来试试手. 本周所选题目:原题目链接 题目详情 题目大意:给出一个字符 ...

  3. 计算机算法设计与分析第四版复习,计算机算法设计与分析(第4版)第1章.ppt

    <计算机算法设计与分析(第4版)第1章.ppt>由会员分享,可在线阅读,更多相关<计算机算法设计与分析(第4版)第1章.ppt(50页珍藏版)>请在人人文库网上搜索. 1.计算 ...

  4. 计算几何学习总结(使用教材算法设计与分析(第二版))

    ** 计算几何总结(使用教材算法设计与分析(第二版)李春葆 清华大学出版社) ** (代码大部分为书中原有代码,如有雷同,实属正常.) #include<bits/stdc++.h> us ...

  5. SDU 2021.1 算法设计与分析考试 回忆版

    SDU 2021.1 计科 算法设计与分析考试 计算题 DFSDFSDFS:画出深度优先树:给出每个点的开始时间和结束时间:给出每条边的分类 有向图上的多源最短路径,要求计算distancematri ...

  6. [XJTUSE 算法设计与分析] 第五章 回溯法

    第五章 回溯法 填空题会有代码填空,大题会手动回溯 学习要点 理解回溯法的深度优先搜索策略. 掌握用回溯法解题的算法框架 (1)递归回溯 (2)迭代回溯 (3)子集树算法框架 (4)排列树算法框架 5 ...

  7. 算法设计与分析 实验五 算法综合实验

    实验5.<算法综合实验> 一.实验目的 理解和复习所学各种算法的概念 掌握和复习所学各种算法的基本要素 掌握各种算法的优点和区别 通过应用范例掌握选择最佳算法的设计技巧与策略 二.实验内 ...

  8. educoder算法设计与分析 实验五回溯法

    实验五 回溯法 第1关:排列 第2关:子集合 第3关:TSP问题 第4关:n皇后问题 第5关:0-1背包 第1关:排列 题目描述: 1.设计算法从前m个大写字母(m≤26)种取出n个字母的所有排列(组 ...

  9. 算法设计与分析第2版第一章

    8.一个字符串采用String对象存储,设计一个算法判断该字符串是否为回文. package a; public class Test01 { public static void main(Stri ...

  10. 【Algorithm】算法设计与分析(第二版)- 王红梅 - JAVA / C++实现:3.9 荷兰国旗问题

    题目 : 荷兰国旗问题.要求重新排列一个由字符R,W,B(R代表红色,W代表白色,B代表兰色,这都是荷兰国旗的颜色)构成的数组,使得所有的R都排在最前面,W排在其次B排在最后.为荷兰国旗问题设计一个算 ...

最新文章

  1. 新发现为类脑计算机开辟了道路
  2. android中string.xml使用总结,string.xml 的作用以及意义——国际化应用
  3. 产品经理有哪些类型?
  4. oracle_Grid Infrastructure 启动的五大问题
  5. IdentityServer4支持的授权类型以及组合
  6. 十九、Oracle学习笔记:行变量
  7. Atitit org.eclipse.jdt 的ast 架构 Eclipse JDT API spec
  8. python登陆linkedin过程分析,及二次验证(一)
  9. hashmap java 排序_Java HashMap 默认排序
  10. c语言智能车跑道检测程序,基于金属检测的智能循迹小车设计
  11. APP色彩搭配方案是由主色、辅助色和点缀色构成
  12. SCIgen与野鸡期刊的梗
  13. 华为手机鸿蒙系统测评,华为发布的鸿蒙系统到底有多牛(让理想成为现实)
  14. [Java基础]-- Jsp 介绍
  15. 同轴电缆抗干扰措施(二)
  16. 笔记本喇叭无声音解决方案
  17. java dozer,MapStruct相当于提示(Dozer)?
  18. 如何制作一个可以自动更新的Github个人主页
  19. SpringBoot2.0整合Redis实战
  20. 清华大学计算机系刘斌,清华大学计算机科学与技术系导师简介:林闯

热门文章

  1. python如何创建文件_python中创建文件、读取文件内容
  2. php图片合并成图片、合并成pdf
  3. 网络安全概论——防火墙原理与设计
  4. win10/win11/win server 安装.net 5/6 配置iis
  5. 闻一以知十,前端要会的10道面试题(附答案与解析)
  6. Python限制函数执行时间的实用解决方案
  7. JSP的内置对象有哪些?
  8. 宫崎骏的幻想世界6页 动漫主题 我愿称之为最美的网页设计作业
  9. 坑!计蒜客——乳草的侵占
  10. UE4 手电筒射线检测