动态规划是一种思想,是一种解决方法,并非一种特定的算法。动态规划最重要的是状态和状态转移方程。是否是感受仍是听不懂这动态规划究竟是啥?听起来就很牛皮,感受彻底学不会?其实并非这么难理解,下面就结合一道例题来说解一下https://vjudge.net/problem/POJ-3624ios
有N种类型手镯,有着不一样的属性,重量w和魅力值d,一我的想装备这些手镯,他有一个载重上限M,而且他想尽量提升本身的魅力值,求最大的魅力值。算法
好了,如今让咱们简单分析一下数组
那么,这题的状态是什么?咱们经过上面的分析能够很简单地得出,状态就是不一样负重下装备不一样的手镯。咱们怎么把不一样的负重和不一样类型手镯对应起来呢?咱们能够很容易想到用一个二维数组,行是不一样的负重,列是不一样的手镯,行列对应的值表明当前的魅力值,这样就把全部的状态都存进来了。spa
ps.这里的列不是表明单纯只放这种类型手镯,而包括了前面放的手镯。.net
咱们不妨令该数组为 D[M][N]
,对于D[M][N]
来讲,它的值有两种取值状况,一种是M的值小于w[N]的值,也就是当前负重不能放下第N个手镯,那么就有D[M][N]=D[M][N-1]
,也就是不放第N个手镯。另外一种就是M的值大于w[N]的值,也就是能够放下第N个手镯,那么就有D[M][N]=D[M-w[N]][N-1]+d[N]
。题目是求最大魅力值,那么转移方程也就出来了D[M][N]=max(D[M-w[N]][N-1]+d[N],D[M][N-1])
。咱们经过转移方程,能够发现,要想知道有N个手镯装备的魅力值,就要知道有N-1个手镯装备的魅力值,最终就归结到只有一个手镯的魅力值。code
咱们根据例题中的样例数据画出以下表格,记住,表格应该是从最底下那行开始往上画。blog
手镯类型\载重上限 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | 4 | 7 | 12 | 16 | 19 | 23 |
2 | 0 | 7 | 12 | 13 | 19 | 19 |
3 | 0 | 7 | 12 | 12 | 19 | 19 |
4 | 0 | 7 | 7 | 7 | 7 | 7 |
咱们能够很容易地从图中得知负重上限最大为6的时候,魅力值最大为23。ci
咱们简单验证一下,对于D16,要看D25和D26,D25和D26都是19,可是D25+d1>D26,因此D16=19+4=23。get
D25要看D35和D33,D33+d2=18,D35=19,故D25=19。string
咱们能够发现,要想知道当前层的状况,首先要知道下一层的状况,也就是二维数组其实能够用一维数组来代替。须要注意的一点是,如图
咱们发现,上一行的值取决于下一行同一列的值或者前面的列的值。因此,计算该一维数组值的时候,应该从后往前计算。
#include<iostream> #include<string> using namespace std; int w[3500]; int v[3500]; int f[12900]; int max(int x, int y) { return x > y ? x : y; } int main() { memset(f, 0, sizeof(f)); memset(w, 0, sizeof(w)); memset(v, 0, sizeof(v)); int N, M; while (cin >> N >> M) { for (int i = 1; i <= N; i++) { cin >> w[i] >> v[i]; } for (int i = N; i >0; i--) { for (int j = M; j > 0; j--) { if (j >= w[i]) { f[j] = max(f[j - w[i]] + v[i], f[j]); } } } cout << f[M] << endl; } return 0; }