前言:

  背包问题所涉及的是经典的动态规划算法。因为长时间不AC了,渐渐感觉思维也都麻了!本文将基础的背包问题做个小结,方便以后翻阅。感兴趣的朋友也可以阅读一下~
------------------------
(1)如何从n个重量和价值分别为Vi、Wi的物品中选择一或多个放入最大容纳量为S的背包使其总价值最大?

输入:

5 10   (分别表示:n,S)
2 3
7 5
3 1
5 10
2 2

5 6
2 3
7 5
3 1
5 10
2 2

输出:

15

10

分析:
f[i][j]:表示背包在存放了前i件物品占据j重量时的价值
其中,1<=i<=n,0<=j<=S;

当我到达某一个状态,需要选择是否将第i件物品放入我的背包时,必须考虑值不值的问题,即:
f[i][j] = max(f[i-1][j],f[i-1]][j-w[i]]+v[i]);

理解了上面的状态转移方程之后,就可以方便得出下面的伪代码了:

  f[0...n][0...S] <- 0 //初始化
  for i<-1:n
    for j<-w[i]:S
      f[i][j] = max(f[i-1][j],f[i-1]][j-w[i]]+v[i]); //状态转移

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 int f[maxn][maxn];
 7 int main(){
 8     //数据从文件读入
 9     freopen("datain.txt","r",stdin);
10     int n,S,a,b;
11     while(scanf("%d%d",&n,&S)==2){
12         memset(f,0,sizeof(f));
13         for(int i=1;i<=n;i++){
14             scanf("%d%d",&a,&b);
15             for(int v=1;v<=S;v++){
16                 if(v>=a)        //do not neglect 'v<a'
17                     f[i][v] = max(f[i-1][v],f[i-1][v-a]+b);
18                 else
19                     f[i][v] = f[i-1][v];
20             }
21         }
22         printf("%d\n",f[n][S]);
23     }
24     return 0;
25 }

以上算法的时间复杂度、空间复杂度均为:O(n*S)

f[i][j]的变化过程:

-----------------------------

|   0 3 3 3 3 3 3 3 3 3           |

|   0 3 3 3 3 3 5 5 8 8           |
|   0 3 3 3 4 4 5 5 8 8           |  
|   0 3 3 3 10 10 13 13 13 14 |
|   0 3 3 5 10 10 13 13 15 15 |

-----------------------------

在深入理解了状态转移方程之后,我们其实还可以对空间进行优化,仅用f[i]表示:背包质量达到i是获得的价值。对应的伪代码如下:

  f[0...S]<-0
  for i<-1:n
    for j<-S:w[i] //从右往左更新!
      f[j] = max(f[j],f[j-w[i]]+v[i]);

对空间进行优化后的代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 int f[maxn];
 7 int main(){
 8     freopen("datain.txt","r",stdin);
 9     int n,S,a,b;
10     while(scanf("%d%d",&n,&S)==2){
11         memset(f,0,sizeof(f));
12         for(int i=0;i<n;i++){
13             scanf("%d%d",&a,&b);
14             for(int v=S;v>=a;v--){
15                 f[v] = max(f[v],f[v-a]+b);
16             }
17         }
18         printf("%d\n",f[S]);
19     }
20     return 0;
21 }

(2)如何从n个重量和价值分别为Vi、Wi的物品中选择一或多个放入最大容纳量为S的背包在背包刚好装满情况下,使其总价值最大?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 int f[maxn];
 7 int main(){
 8     freopen("datain.txt","r",stdin);
 9     int n,S,a,b;
10     while(scanf("%d%d",&n,&S)==2){
11         for(int i=1;i<=S;i++) f[i]=-0xfffffff;   //最小的int
12         f[0]=0;
13         for(int i=0;i<n;i++){
14             scanf("%d%d",&a,&b);
15             for(int v=S;v>=a;v--){
16                 f[v] = max(f[v],f[v-a]+b);
17             }
18         }
19         printf("%d\n",f[S]);
20     }
21     return 0;
22 }

View Code

输入:

5 10   (分别表示:n,S)
2 3
7 5
3 1
5 10
2 2

输出:14

(3)如何从n种(每种无限个)重量和价值分别为Vi、Wi的物品中选择一或多个放入最大容纳量为S的背包使其总价值最大?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 int f[maxn];
 7 int main(){
 8     freopen("datain.txt","r",stdin);
 9     int n,S,a,b;
10     while(scanf("%d%d",&n,&S)==2){
11         memset(f,0,sizeof(f));
12         for(int i=0;i<n;i++){
13             scanf("%d%d",&a,&b);
14             for(int v=a;v<=S;v++){
15                 f[v] = max(f[v],f[v-a]+b);
16             }
17         }
18         printf("%d\n",f[S]);
19     }
20     return 0;
21 }

View Code

输入:

5 6
2 3
7 5
3 1
5 10
2 2

输出:10

(4)如何从n种(每种无限个)重量和价值分别为Vi、Wi的物品中选择一或多个放入最大容纳量为S的背包在背包刚好装满情况下,使其总价值最大?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 int f[maxn];
 7 int main(){
 8     freopen("datain.txt","r",stdin);
 9     int n,S,a,b;
10     while(scanf("%d%d",&n,&S)==2){
11         for(int i=0;i<=S;i++) f[i]=-0xfffffff;
12         f[0]=0;
13         for(int i=0;i<n;i++){
14             scanf("%d%d",&a,&b);
15             for(int v=a;v<=S;v++){
16                 f[v] = max(f[v],f[v-a]+b);
17             }
18         }
19         printf("%d\n",f[S]);
20     }
21     return 0;
22 }

View Code

输入:

5 6
2 3
7 5
3 1
5 10
2 2

输出:9

----------------------------------------------
结语:
本文限于篇幅就只是对最最基本的01背包问题作了个人的分析,后面的3个扩展只贴代码,希望感兴趣的朋友们可以旁击侧敲吧~有问题或独特见解的博友请留言~

转载于:https://www.cnblogs.com/SeaSky0606/p/4743758.html

动态规划--重拾我的“背包”相关推荐

  1. CSS魔法堂:重拾Border之——图片作边框

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  2. 重拾-Spring Transaction

    问题 面试中是不是有时经常会被问到 "Spring 事务如何管理的了解吗?" ,"Spring 事务的传播性有哪些,能聊聊它们的使用场景吗?", "事 ...

  3. 重拾算法(3)——用458329个测试用例全面测试二叉树和线索二叉树的遍历算法

    重拾算法(3)--用458329个测试用例全面测试二叉树和线索二叉树的遍历算法 在"上一篇"和"上上一篇"中,我给出了二叉树和线索二叉树的遍历算法.给出算法容易 ...

  4. CSS魔法堂:重拾Border之——更广阔的遐想

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  5. 重拾CCNA,学习笔记持续更新ing......(4)

    重拾CCNA,学习笔记持续更新ing......(4) 路由器作用功能的经典解说(笑)(非原创) 假设你的名字叫小不点,你住在一个大院子里,你的邻居有很多小伙伴,在门口传达室还有个看大门的李大爷,李大 ...

  6. reid 数据集 行人重拾别

    行人重拾别 数据集 jacke121 数据集描述 Market-1501 https://blog.csdn.net/ctwy291314/article/details/83544088 数据集描述 ...

  7. Java入门算法(动态规划篇2:01背包精讲)

    本专栏已参加蓄力计划,感谢读者支持❤ 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算 ...

  8. 重拾强化学习的核心概念_强化学习的核心概念

    重拾强化学习的核心概念 By Hannah Peterson and George Williams (gwilliams@gsitechnology.com) 汉娜·彼得森 ( Hannah Pet ...

  9. php byte stringbuffer,重拾java基础(十三):String姐妹StringBuffer、StringBuilder总结

    重拾java基础(十三):String姐妹StringBuffer.StringBuilder总结 一.StringBuffer类概述buffer:缓冲 2. 字符串缓冲区,跟String非常相似,都 ...

最新文章

  1. AC日记——字符串最大跨距 openjudge 1.7 26
  2. yum安装mysql
  3. BLE 安全之虫洞攻击
  4. 安全手册(初稿)[转]
  5. zoom 用户被锁定_重新考虑Zoom的用户体验
  6. 前端,你要知道的SEO知识
  7. day31 模块 与包
  8. 从github安装python项目
  9. 因为计算机丢失d3dx10,Win7打开剑灵游戏提示丢失d3dx10_43.dll怎么解决
  10. 小米网页连接调用服务器,小米6浏览器远程代码执行(CVE-2019-13322)
  11. 聚类的方法、原理以及一般过程
  12. (四)机器学习方法的分类
  13. php excel引入tp,TP 引入phpExcel
  14. vbs 打开指定浏览器网页
  15. python一行输入两个数据中间用空格隔开
  16. Hello ......
  17. 异地多活高可用架构设计实践与思考
  18. 全排列问题(AcWing 823. 排列)
  19. (附源码 )SSM+mysql+微信小程序网易云音乐设计与实现 毕业设计261620
  20. Pygame详解(十六):cursors 模块

热门文章

  1. java image 设置大小_如何在Java中调整BufferedImage的大小
  2. notebook打开外部文件_CAD外部参照真是个好东西!
  3. 群晖 上传 源文件不存在_群晖NAS连接百度网盘报错?原因是这样的
  4. 发动机冷启动和热启动的区别_「牛车实验室」AGM自动启停蓄电池解读 和普通蓄电池到底有什么区别...
  5. star-cd linux安装,linux 使用PXE方式,kickstar网络安装系统
  6. java8日期_Java8日期与时间
  7. [渝粤教育] 西南政法大学 法理学 参考 资料
  8. [渝粤教育] 广东-国家-开放大学 21秋期末考试财政学10573k1
  9. 【渝粤题库】陕西师范大学200471 英汉翻译
  10. [渝粤题库]陕西师范大学《幼儿园社会教育》作业