动态规划(DP)

01背包问题(0,1的意思就是只能取一次或者不取)

       有n个重量和价值分别为wi和vi的物品。从这些物品中挑选出总质量不超过w的物品,求所有挑选方案中质量和的最大值。

     如果我去模拟一下这个问题:每个物品都可以选择或不选择。假设我从第i个物品挑选总重量小于j的物品:

int rec(int i, int j){
	int res;
	if(i == n) res = 0;
	else if(j < wei[i]) res = rec(i + 1, j);  //无法挑选此物品,挑选下一个物品
	else res = max(rec(i + 1, j), rec(i + 1, j - wei[i]) + val[i]); 
} 

     rec(i + 1, j)表示不选择第i个物品        rec(i + 1, j - wei[i]) + val[i]  表示选择了第i个物品,所以要加上第i个物品的质量,然后进行比较,取使得质量最大的情况

 

    递归调用的过程中会出现重复的现象,为了避免这一现象的发生,我们可以将返回的结果记录下来,使得下一次不在去计算。

int n, w;
int wei[maxn], val[maxn];
int dp[maxn][maxn];    //用数组去记录,如果算过记为1,没有算过记为0

int rec(int i, int j){
	if(dp[i][j] >= 0) return dp[i][j];  //计算过的话直接使用之前的结果
	
	int res;
	if(i == n) res = 0;
	else if(j < wei[i]) res = rec(i + 1, j);
	else res = max(rec(i + 1, j), rec(i + 1, j - wei[i]) + val[i]);
	
	return dp[i][j] = res;
}
void solve(){
	memset(dp, -1, sizeof(dp));
	printf("%d\n", rec(0, w));
} 
int main()
{
	while(scanf("%d%d", &n, &w) != EOF){
		solve();
	}
}

将此代码写为递归方程 :dp[i][j] = 0;

                                         dp[i][j] = dp[i + 1][j]     当j <wei[i];

                                         dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - wei[i]] + val[i]);      当j>=wei[i];

                                         写为for循环:

for(int i = n-1; i >= 0; i--){
		for(int j = 0; j <= w; j++){
			if(j < wei[i]) dp[i][j] = dp[i+1][j];
			else dp[i][j] = max(dp[i+1][j], dp[i+1][j-wei[i]] + val[i]);
		}
	}
	printf("%d\n", dp[0][w]);

来源于:挑战

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值