您的位置:首页 > 其它

hihocoder(1038,1043) 01背包与完全背包

2015-04-13 10:39 316 查看
动态规划是一直感觉比较模糊的东西,虽然大致上知道是什么一回事,但是离灵活应用还差得远,但貌似比赛中动态规划的题出的特别多,这两个经典问题其实只能算是一个学习动态规划很好的模型。不过万事开头难,关键还是得静下心来多练习。

01背包的状态转移式f(i, j) = max{f(i-1, j), f(i-1, j-need[i])+value[i]}

直接按照上述的状态转移式申请二维数组进行运算,伪代码如下:

fori : 1..N  

  f(0,j) = 0

for i : 1..N

  for j : 0..M

    if(j < need(i))  f(i, j) = f(i-1, j)

    else  f(i, j) = max{f(i-1, j), f(i-1, j-need[i])+value[i]}

但是这样写,空间复杂度是非常大的,因为有一个很大的二维数组,但是仔细观察公式,或者在纸上画画格子,就会发现,每次计算所需要的只是i-1行的数据,因此,很容易想到的是可以用两行一维数组交替使用即可,但是,再仔细观察,会发现每次计算都是用的左上方的数据,这样也就是说,如果反过来计算:

for i:1..N

  for j: M..need(i)

    f(j) = max{f(j), f(j-need(i))+value(i)}

就不会覆盖“左上方”的数据,并且能顺利完成整个状态转移量的计算。

代码其实就是状态转移式了,所以说动态规划的问题,只要能列出正确的状态转移式,离AC也就不远了。

Impl:

#include <iostream>
using namespace std;

int main()
{
int N,M;
cin >> N >> M;
int *need = new int
;
int *value = new int
;
for (int i = 0; i < N; ++i)
cin >> need[i] >> value[i];
int *dp = new int[M];

for (int i = 0; i < M; ++i)
dp[i] = 0;
for (int i = 0; i < N; ++i)
for (int j = need[i]; j < M; ++j)
dp[j] = max(dp[j], dp[j-need[i]]+value[i]);

cout << dp[M-1] << endl;

delete [] need;
delete [] value;
delete [] dp;

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: