背包问题(动态规划基础)

01背包问题

dp[i][j]表示的是要存放第i个物品时,背包此时的容量为j,背包内物品的总价值

weight表示物品占据背包的体积

dp[i][j]=(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);//状态转移方程

我们之前看的关于dp的问题,对于每一个元素的处理方法就是选和不选

我们的状态转移方程也是根据这个得出的

01背包问题动态规划模板:

void dp(){
	for(int i=1;i<=number;i++){
		for(int j=1;j<=capacity;j++){
			if(j<w[i]){
				v[i][j]=v[i-1][j];
			}
			else{
				if(v[i-1][j]>v[i-1][j-w[i]]+v[i]){
					v[i][j]=v[i-1][j];
				}else{
					v[i][j]=v[i-1][j-w[i]]+v[i];
				}
			}
		}
	}
}

总结:利用动态规划解决背包问题的效率即是填写此张表的效率,
所以动态规划的时间效率为O(number*capacity)=O(n*c),
由于用到二维数组存储子问题的解,所以动态规划的空间效率为O(n*c);

void FindWhat(int i,int j)//寻找解的组成方式
{
    if(i>=0)
    {
        if(V[i][j]==V[i-1][j])//相等说明没装
        {
            item[i]=0;//全局变量,标记未被选中
            FindWhat(i-1,j);
        }
        else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
        {
            item[i]=1;//标记已被选中
            FindWhat(i-1,j-w[i]);//回到装包之前的位置
        }
    }
}

完全背包问题

完全背包是在01背包的基础上进行进阶的,01背包之所以在背包前加个01是因为物品每种只有一个,两种状态,放与不放,放就是1,不放就是0

完全背包比01背包多的条件是物品不止一个,会有多个物品,我们可以选择多个相同的物品放入背包

void packageTotal(){
    for(int i = 1; i <= N; i++){
	    for(int j = 1; j <= M; j++){
		    if(weight[i] > j){	//如果重量比容量大,放不下,就不放				                
                        V[i][j] = V[i - 1][j];
		    }
			else{ //其实 if跟else可以去掉的
				int k = j / weight[i];	//如果能放下,要看看能放几个,然后放几个跟不放所有情况比一下看哪个价值最大,除法默认向下取,也可以用floor()
				for(int m = 0; m <= k; m++){
					if(V[i - 1][j - m * weight[i]] + m * value[i] > V[i][j])
					{
						V[i][j] = V[i - 1][j - m * weight[i]] + m * value[i];
					}
				}
			}
		}
	}
}

背包问题相关优秀博文:
教你彻底学会动态规划——入门篇
动态规划三部曲之一个故事教你透彻理解动态规划(一)

https://blog.csdn.net/qq_38749759/article/details/77406397
https://blog.csdn.net/na_beginning/article/details/62884939
https://blog.csdn.net/m0_37907835/article/details/78991992

猜你喜欢

转载自blog.csdn.net/Helloirbd/article/details/86748509