关于动态规划原理的一些理解(二维0/1背包)

1、基本原理

动态规划通过拆分问题,将原问题拆分成几个子问题,定义问题状态和状态之间的关系(这里就是动态规划的状态转移方程或者是递推公式),使得问题通过地推地方式去解决。这里求解任意子问题时,通过决策使得该子问题可能达到局部的最优解,然后舍弃其它的解法,依次解决,最后一个问题就是整个问题的最终(最优)解。

这里我们以0/1背包问题的动态规划的例子来说

  1. 题目介绍
    有 N 件物品和一个容量为 V 的背包,每件物品有各自的价值且只能被选择一次,要求在有限的背包容量下,装入的物品总价值最大。
    2.「0-1 背包」是较为简单的动态规划问题,也是其余背包问题的基础。

动态规划是不断决策求最优解的过程,「0-1 背包」不断对子问题进行最优化讨论决策,「0-1」正好代表不选与选两种决定。

2、这里我们以二维数组为例

f[i][j]:第i个物品放入容量为j的背包的最大价值
这里有两个状态转移:
(1)当当前背包容量不足以放入当前物品时(j < weight[i])该状态一定由上一个不放入第i个物品时的最优解得到
对应的状态转移方程:f[i][j] = f[i - 1][j];
(2)当该物品能放入背包时,也有一种情况就是该物品完全占据容量为j的背包,它对应的背包价值与不放入按上一个状态的最优解进行比较;还有一种就是当我放入第i个物品后,我扣除第i个物品的重量后的价值加上我现在第i个物品的价值。这两种情况其实在过程中其实有共融的地方,我这里根据我自己的理解来进行一个阐述。上面两种均与不放入的情况进行一个比较,两者取最优解就好。
对应的状态转移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j - weight[i]] + value[i]);

两种情况我们这里均取最大值(即最优化)即可。

#include<iostream>
using namespace std;
void BagProblem(){
	int num;
	int weight[25] = {2,2,6,5,4};
	int value[25] = {6,3,5,4,6};
	//cout << "请输入物品个数:"<<endl;
    //cin >> num;
	int bagweight ;
	cout<< "请输入背包容量 :"<<endl;
	cin >> bagweight; 
	int dp[5][bagweight+1];
	for(int j = 0; j < weight[0]; j++){
		dp[0][j] = 0;
	}
	for(int j = weight[0]; j <= bagweight; j++){
		dp[0][j] = value[0];
	}
	for(int i = 1;i < 5; i++){
		for(int j = 0;j <= bagweight; j++){
			if(j < weight[i]){
				dp[i][j] = dp[i-1][j];
			}
			else{
				dp[i][j] = max(dp[i-1][j] ,dp[i-1][j-weight[i]] + value[i]); 
			}
		}
	}
	for(int i = 0;i < 5; i++){
		for(int j = 0;j <= bagweight; j++){
			cout<<dp[i][j]<<" ";
		}
		cout<<endl;
	}
	cout << "背包能放的最大价值为: " << dp[4][bagweight] << endl;
}
int max(int dp1,int dp2){
	
	if(dp1>dp2){
		return dp1;
	}
	return dp2;
}
int main(){
	BagProblem();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值