动态规划DP入门 0-1背包
2017-11-01 12:54
363 查看
人生第一篇博客……写个简单点的……
作为一个炒鸡蒟蒻,在第一次看到0-1背包问题时,我就一个想法:
贪心。
然后我就这么干了……
预处理伪代码如下:
也就是求利润率之类的……
但是,这么写过的童鞋都知道,这样肯定是不能A题的。
于是,我们就需要一种高级的算法——
然后我就来解释一下吧……
无后效性:指现在对数据做的操作不会影响以后的操作
举个栗子:
比如方格取数这道题目
虽然这道题目的标签有一个DP……作为一个不会dp的人一眼看去肯定是做两遍
那么就有问题了:把一个格子的值去掉会对另一个人的值影响,所以这道题用非dp做法是有后效性的
所以我们要用DP做 当然这不是我们研究的重点
接下来我们研究0-1背包
其实我一直都不太理解0-1是什么意思 大概是从无到有的意思吧
例题见 采药
于是我们又要带进状态和状态转移方程这两个概念了
状态:指的是程序进行到某个阶段时的值(好草率啊)
状态转移方程:由一个状态转到另一个状态的方程
DP还有一个特点,就是将大问题分解成小问题,有点类似于分治
这里就要用到一种强大而平常的工具:EXCEL
以采药为例:
我们设 f[i] 表示我们用了 i 的时间所能采到的最大价值
设计一组输入样例:
然后上EXCEL:
设横轴为时间
得到这样一张表:
然后我们针对每一时间,得到能够采到的最大价值。
然后填完这张表。
我们先把转移方程打出来,配合表理解:
f[j]=max(f[j],f[j−w[i]]+c[i]) w是时间,c是价值
然后把表填起来:
然后就可以得出解了,答案在 f[v] 的位置
转移方程的理解:
在当前时间下,可以做两种决策:
- 采这种药,可以发现价值为 f[j−w[i]]+c[i]
- 不采这种药,价值为 f[j]
在这两个里找出最大的,就可以得出方程了
附代码:
C++:
Pascal:
写的不好,请多吐槽
作为一个炒鸡蒟蒻,在第一次看到0-1背包问题时,我就一个想法:
贪心。
然后我就这么干了……
预处理伪代码如下:
for(int i=1;i<=n;i++) { cin >> w[i] >> c[i]; t[i]=c[i]/w[i]; }
也就是求利润率之类的……
但是,这么写过的童鞋都知道,这样肯定是不能A题的。
于是,我们就需要一种高级的算法——
动态规划~
然后我就一脸mengbi地听着老师打着EXCEL说着什么无后效性什么转移方程然后我就来解释一下吧……
无后效性:指现在对数据做的操作不会影响以后的操作
举个栗子:
比如方格取数这道题目
虽然这道题目的标签有一个DP……作为一个不会dp的人一眼看去肯定是做两遍
那么就有问题了:把一个格子的值去掉会对另一个人的值影响,所以这道题用非dp做法是有后效性的
所以我们要用DP做 当然这不是我们研究的重点
接下来我们研究0-1背包
其实我一直都不太理解0-1是什么意思 大概是从无到有的意思吧
例题见 采药
于是我们又要带进状态和状态转移方程这两个概念了
状态:指的是程序进行到某个阶段时的值(好草率啊)
状态转移方程:由一个状态转到另一个状态的方程
DP还有一个特点,就是将大问题分解成小问题,有点类似于分治
这里就要用到一种强大而平常的工具:EXCEL
以采药为例:
我们设 f[i] 表示我们用了 i 的时间所能采到的最大价值
设计一组输入样例:
5 3 3 2 1 4 4 5
然后上EXCEL:
设横轴为时间
得到这样一张表:
然后我们针对每一时间,得到能够采到的最大价值。
然后填完这张表。
我们先把转移方程打出来,配合表理解:
f[j]=max(f[j],f[j−w[i]]+c[i]) w是时间,c是价值
然后把表填起来:
然后就可以得出解了,答案在 f[v] 的位置
转移方程的理解:
在当前时间下,可以做两种决策:
- 采这种药,可以发现价值为 f[j−w[i]]+c[i]
- 不采这种药,价值为 f[j]
在这两个里找出最大的,就可以得出方程了
附代码:
C++:
#include<cstdio> #include<algorithm> using namespace std; struct bag { int g,p; }t[100005]; int sum[100005]; int main() { int w,n,i,j; scanf("%d%d",&w,&n); for(i=1;i<=n;i++) scanf("%d%d",&t[i].g,&t[i].p); for(i=n;i>=1;i--) for(j=w;j>=t[i].g;j--)sum[j]=max(sum[jt[i].g]+t[i].p,sum[j]); printf("%d",sum[w]); return 0; }
Pascal:
var i,j,n,v:integer; f:array[1..2005] of integer; w,p:array[1..2005] of integer; begin readln(v,n); for i:=1 to n do readln(w[i],p[i]); for i:=1 to n do begin for j:=v downto w[i] do begin if f[j]<f[j-w[i]]+p[i] then f[j]:=f[j-w[i]]+p[i]; end; end; writeln(f[v]); end.
写的不好,请多吐槽
原创 By Venus
相关文章推荐
- dp入门与两个基础的背包问题
- 动态规划入门之背包问题
- 多重背包的入门题目HDU1171,2191,2844.
- HDU 1284 钱币兑换问题(完全背包:入门题)
- 关于动态规划的一个精彩的入门文章(背包)
- HDOJ 1712 ACboy needs your help(分组背包入门)
- UVA - 147 Dollars (完全背包 入门题)
- hdu 2602 (01背包入门)
- 完全背包入门题【简单到死啊】
- hdu 2602 Bone Collector (01背包 入门)
- POJ-3624 Charm Bracelet (01背包 入门题)
- POJ-1787 Charlie's Change (完全背包+输出方案 入门题)
- [学习]背包问题入门(1)
- hdu 2602 Bone Collector (0 1背包入门)
- DP算法入门(2)——完全背包问题(POJ2063题解)
- 背包问题入门(单调队列优化多重背包
- HDU 3466 【DP入门之01背包】
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包,经典入门题)
- 动态规划[入门3]-多重背包问题
- NYOJ860:又见01背包(01背包入门2)