题目引入:

有n个重量和价值分别为Wi,Vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中的价值总和的最大值。

分析:

首先,我们用最普通的方法,针对每个物品是否放入背包进行搜索。

#include<iostream>
#include<stdio.h>
using namespace std;
int n,W;
int w[100],v[100];
///从第i个物品开始挑选总重量小于j的部分
int res(int i,int j)///i表示第i件物品,j表示的是当前背包的剩余容量
{
int ans;
if(i==n)///已经没有剩余物品了
ans=0;
else if(j<w[i])///当前的背包容量不够放第i件物品
{
ans=res(i+1,j);///直接看第i+1件物品
}
else
{
///看一下到底是第i件物品放还是不放获得的价值大
ans=max(res(i+1,j),res(i+1,j-w[i])+v[i]);
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d%d",&w[i],&v[i]);
}
scanf("%d",&W);
printf("%d\n",res(0,W));
return 0;
}

对于这个方法,可以明显的看出来他的搜索深度为n,对于n=4,Wi和Vi分别为{(2,3),(1,2),(3,4),(2,2)}切W为5的情况下,我们看一下res函数的递归执行过程。

从图中我们可以看出res以(3,2)为参数调用了两次,因此我们可以把第一次的计算结果保存下来,就可以在下次直接调用。

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int n,W;
int w[100],v[100];
int dp[100][100];
///从第i个物品开始挑选总重量小于j的部分
int res(int i,int j)///i表示第i件物品,j表示的是当前背包的剩余容量
{
if(dp[i][j]>0)
return dp[i][j];
int ans;
if(i==n)///已经没有剩余物品了
ans=0;
else if(j<w[i])///当前的背包容量不够放第i件物品
{
ans=res(i+1,j);///直接看第i+1件物品
}
else
{
///看一下到底是第i件物品放还是不放获得的价值大
ans=max(res(i+1,j),res(i+1,j-w[i])+v[i]);
}
return dp[i][j]=ans;
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d%d",&w[i],&v[i]);
}
scanf("%d",&W);
memset(dp,-1,sizeof(dp));
printf("%d\n",res(0,W));
return 0;
}

接下来,我们看一下记忆化数组。记dp(i)(j)为从第i个物品开始挑选总重小于j是,总价值的最大值。因此可得到递推公式:

dp[n][j]=0;
dp[i][j]=dp[i+1][j];///当j<w[i]
dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);///当j>=w[i]

因此可以不用递归函数,直接用递推公式将各项的值计算出来。

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int n,W;
int w[100],v[100];
int dp[100][100];
void solve()
{
for(int i=n-1; i>=0; i--)
for(int j=0; j<=W; j++)
{
if(j<w[i])
dp[i][j]=dp[i+1][j];
else
dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
}
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d%d",&w[i],&v[i]);
}
scanf("%d",&W);
memset(dp,0,sizeof(dp));
solve();
printf("%d\n",dp[0][W]);
return 0;
}

刚刚讲到的dp中关于i的循环是逆向进行的。如果更改递推关系式的话循环就可以正向进行。

///dp[i][j],表示从0到i这i+1个物品中选出总重量不超过j的物品时总价值的最大值
dp[0][j]=0;
dp[i+1][j]=dp[i][j];/// j<w[i]
dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);//其他

则上面的solve函数进行相应的修改

void solve()
{
for(int i=0;i<n;i++)
for(int j=0; j<=W; j++)
{
if(j<w[i])
dp[i+1][j]=dp[i][j];
else
dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
}
}

01背包入门 dp的更多相关文章

  1. 九度OJ 1030:毕业bg (01背包、DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1814 解决:798 题目描述:     每年毕业的季节都会有大量毕业生发起狂欢,好朋友们相约吃散伙饭,网络上称为"bg" ...

  2. [LeetCode]494. 目标和、416. 分割等和子集(0-1背包,DP)

    题目一 494. 目标和 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前 ...

  3. CoderForces 687C The Values You Can Make (01背包,DP)

    题意:给定 n 个硬币和一个值 k,问你在用一些硬币组成面值为 k的这些硬币还能组成多少种其他面值. 析:如果这样说,由这些硬币能组成多少种不同的面值,那么是不是就很熟悉了,这不就是01背包么,这个题 ...

  4. 九度OJ 1123:采药 (01背包、DP、DFS)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2705 解决:1311 题目描述: 辰辰是个很有潜能.天资聪颖的孩子,他的梦想是称为世界上最伟大的医师. 为此,他想拜附近最有威望的医师为师 ...

  5. 九度OJ 1152:点菜问题 (01背包、DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1046 解决:543 题目描述: 北大网络实验室经常有活动需要叫外买,但是每次叫外买的报销经费的总额最大为C元,有N种菜可以点,经过长时间的 ...

  6. HDU 1203 I NEED A OFFER (01背包&&概率dp)

    M - I NEED A OFFER! Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  7. 01背包----简单DP

    描述 且说上一周的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励的时刻了! 小Ho现在手上有M张奖券,而奖品区有N件奖品,分别标号为1到N,其中第i件奖品需要ne ...

  8. 九度OJ 1025:最大报销额 (01背包、DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4352 解决:1055 题目描述:     现有一笔经费可以报销一定额度的发票.允许报销的发票类型包括买图书(A类).文具(B类).差旅(C ...

  9. HDU 1203 I NEED A OFFER!(01 背包DP)

    点我看题目 题意 : 中文题不详述. 思路 :类似于01背包的DP,就是放与不放的问题,不过这个要求概率,至少得到一份offer的反面就是一份也得不到,所以先求一份也得不到的概率,用1减掉就可以得到所 ...

随机推荐

  1. TCP系列21—重传—11、TLP

    一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重 ...

  2. 【Docker】- 基本命令

    1.docker ps -a    显示所有容器 2.doker ps -l 显示最近一次启动的容器 3.docker ps   显示正在运行的容器 4.docker start [容器ID]  启动 ...

  3. Cacti自定义脚本,监测Docker信息(Script/Command方式)

    一 环境背景 监控主机A:192.168.24.231:被监控主机B:192.168.24.233 A/B主机,通过公私钥建立ssh连接 [操作B主机时不需要输入密码,详见笔记:http://app. ...

  4. Maven pom 文件解释

    1 - 什么是构建? 我们都知道,写完代码之后需要进行编译和运行,以笔者自身为例,使用 Eclipse 写完代码,需要进行编译,再生成 war 包,以便部署到 Tomcat. 在编写 Java 代码的 ...

  5. 【其他】UTF-8带签名与不带签名

    在 Visual Web Developer 另存为文件时,有编码选项,其中有: Unicode (UTF-8 with signature) - Codepage 65001 Unicode (UT ...

  6. service(ServletRequest req, ServletResponse res) 通用servlet 可以接受任意类型的请求 用于扩展

    service(ServletRequest req, ServletResponse res)   通用servlet 可以接受任意类型的请求  用于扩展

  7. HUAS 1476 不等数列(DP)

    考虑DP. 如果把转移看出当前位填什么数的话,这样是有后效性的. 如果考虑当前的序列是将1至n依次插入序列中的话. 考虑将i插入1到i-1的序列中,如果插入到<号中或者首部,那么最后就会多出一个 ...

  8. select、poll、epoll模型对比

    select.poll.epoll模型对比 先说Select:            1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认32*32=1024. ...

  9. [洛谷P4822][BJWC2012]冻结

    题目大意:有一张$n(n\leqslant50)$个点$m(m\leqslant1000)$条边的无向图,可以使得$k$条边使得边权减半,求最短路 题解:分层图最短路 卡点:无 C++ Code: # ...

  10. [2018国家集训队][UOJ449] 喂鸽子 [dp+组合数学]

    题面 传送门 思路 首先,这道题是可以暴力min-max反演+NTT做出来的......但是这个不美观,我来讲一个做起来舒服一点的做法 一个非常basic的idea:我们发现在一只鸽子吃饱以后再喂给它 ...