五个常用算法(一):动态规划

1.从01背包问题说起

有一堆宝石一共n个,现在你身上能装宝石的就只有一个背包,背包的容量为C。把n个宝石排成一排并编上号: 0,1,2,…,n-1。第i个宝石对应的体积和价值分别为V[i]和W[i] 。背包总共也就只能装下体积为C的东西,那你要装下哪些宝石才能获得最大的利益呢?


我们先来看下在这个问题里,动态规划最重要的两个概念:状态和状态转移方程。


假如现在有3个宝石,体积分别为5,4,3;对应的价值为20,10,12;背包的体积是10。这个问题解容易看出是第0、2个宝石,总价值是22。先考虑第2个宝石,有放入和不放入两种选择,选择放入的话,背包剩下空间7,问题变成用空间7的背包装前2个宝石(最优子结构),表示为d(2,7);不放的话变成空间10背包装前2个,表示为d(2,10)。在这里状态d(i,j)表示前i个宝石装到剩余体积为j的背包里能达到的最大价值,状态转移方程式描述状态之间如何转移,原问题状态是d(3,10),如果装入宝石2,那么d(3,10)=d(2,7)+12=32;如果不装,d(3,10)=d(2,10)=30。可以简写为一个式子d(3, 10)=max{ d(2, 10), d(2, 7)+12 } 。即状态转移方程d(i, j)=max{ d(i-1, j), d(i-1,j-V[i-1]) + W[i-1] } 。

代码实现的话是这样:

for(int i=0;i<n;i++){
    for(int j=0;j<C;j++){
        if(i==0)    d[i][j]=0;
        else{
            if(j>W[i]&&V[i]+d[i-1][j-W[i]]>d[i-1][j])    d[i][j]=V[i]+d[i-1][j-W[i]];
            else    d[i][j]=d[i-1][j];
        }
    }
}

解法的时间复杂度、空间复杂度都是O(nC);

时间复杂度没法优化了,可以看出数组d的更新只用到了i-1的值,所以我们只有必要存储数组d[i-1],空间复杂度可以优化一下。

《五个常用算法(一):动态规划》

代码如下(注意因为更新j分量需要用到比j小的数值,所以按j递减的顺序更新):

memset(d, 0, sizeof(d));
for(int i=0; i<=n; ++i){
    for(int j=C;j>=0; --j){
        if(j>=V [i]&& i>0) d[j] >?= d[j-V[i]]+W[i];
    }
}

最后贴一个完整代码

/**0-1 knapsack d(i, j)表示前i个物品装到剩余容量为j的背包中的最大重量**/
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

int main(){
	freopen("data.in", "r", stdin);
	freopen("data.out", "w", stdout);
	int n, C, V = 0, W = 0;
	while(scanf("%d %d", &n, &C) != EOF){
		int* d = (int*)malloc((C+1)*sizeof(int));
		memset(d, 0, (C+1)*sizeof(int));
		
		for(int i=0; i<=n; ++i){
			if(i>0)	scanf("%d %d", &V, &W);
			for(int j=C; j>=0; --j){
				if(j>=V && i>0)	d[j] >?= d[j-V]+W;
			}
		}
		printf("%d\n", d[C]);
		free(d);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

2.动态规划问题思考

能采用动态规划求解的问题的一般要具有3个性质:

    (1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

    (2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

   (3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(这个性质是动态规划节省时间复杂度的原因


刷题有感:

首先要确定状态和状态转移方程,难点和关键在于找状态转移方程,参考博客:

http://www.360doc.com/content/13/0601/00/8076359_289597587.shtml

    原文作者:动态规划
    原文地址: https://blog.csdn.net/byplane/article/details/52728415
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞