P1164-小A买菜(动态规划,01背包)

动态规划

#include<iostream>
using namespace std;
const long long N = 1e5 + 9;
int dp[1000][1000];
int a[N];
int main() {
	long long m, n,ans=0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 0; i <= n; i++) {
		dp[i][0] = 1;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (j >= a[i]) {
				dp[i][j] += dp[i - 1][j - a[i]];
			}
			dp[i][j] += dp[i - 1][j];
		}
	}
	cout << dp[n][m];
	return 0;
}

P1164-小A买菜(动态规划,01背包) 为所有花费 0 元的商品的方法赋值为 1; 因为花费0元的方法,有且仅有一种,那就是都不买

P1164-小A买菜(动态规划,01背包) 两次循环,外循环为商品的数目,内循环为 花费的钱 ,即表示 每 P1164-小A买菜(动态规划,01背包) 件商品 花费 P1164-小A买菜(动态规划,01背包) 元 的方法数, 先历遍商品数.(动态规划的方程为$ dp[i][j] += dp[i – 1][j – a[i]]$ 就是通过 P1164-小A买菜(动态规划,01背包) 的数目推出 P1164-小A买菜(动态规划,01背包) 的数目,所以先历遍商品数)

if (j >= a[i]) {                     
	dp[i][j] += dp[i - 1][j - a[i]];
}
dp[i][j] += dp[i - 1][j];

其中 P1164-小A买菜(动态规划,01背包) 表示前 P1164-小A买菜(动态规划,01背包) 个商品花费 $ j $ 元的方法数.

P1164-小A买菜(动态规划,01背包)一共有两种情况:

  1. 买第 P1164-小A买菜(动态规划,01背包) 件商品 : P1164-小A买菜(动态规划,01背包) 相当于 在 前 P1164-小A买菜(动态规划,01背包) 件商品 花费 P1164-小A买菜(动态规划,01背包) 元 的基础之上 卖下了花费P1164-小A买菜(动态规划,01背包) 元的 P1164-小A买菜(动态规划,01背包) 这件商品(前提是P1164-小A买菜(动态规划,01背包) 可以买)
  2. 不买第 P1164-小A买菜(动态规划,01背包) 件商品:$dp[i][j] += dp[i – 1][j] $ 那么就表示 前P1164-小A买菜(动态规划,01背包) 件商品 和前 P1164-小A买菜(动态规划,01背包) 件商品一样 花费了 P1164-小A买菜(动态规划,01背包)

因为求的是方法,所以两种情况都要加上, 其中不买 P1164-小A买菜(动态规划,01背包) 这件商品 这种情况一定存在

最后输出 P1164-小A买菜(动态规划,01背包) ,即一共 P1164-小A买菜(动态规划,01背包) 件商品 花费 m元的方法

优化为一维数组

为何可以优化?:

​ 每次循环只用到了 P1164-小A买菜(动态规划,01背包) 的上一个 P1164-小A买菜(动态规划,01背包)

所以由 P1164-小A买菜(动态规划,01背包) 可以变为 P1164-小A买菜(动态规划,01背包)

#include<iostream>
using namespace std;
const long long N = 1e5 + 9;
int dp[N];
int a[N];
int main() {
	long long m, n, ans = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i];
		dp[0]= 1;//表示最初始的那个,第一个商品花费0元的方法为1;
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= 1; j--) {//注意这里要反过来应为dp[j-a[i]]可能已经改变了
         	//这里省略了一步就是 dp[j]=dp[j] 这表示 不买的情况,下一个和上一个的方法数是一样的
			if (j >= a[i]) {
				dp[j] += dp[j - a[i]];//逐渐迭代
			}
		}
	}
	cout << dp[m];
	return 0;
}

P1164-小A买菜(动态规划,01背包) 一维的 P1164-小A买菜(动态规划,01背包) 对比 二维的 P1164-小A买菜(动态规划,01背包)

  • P1164-小A买菜(动态规划,01背包) , 表示 花费P1164-小A买菜(动态规划,01背包)元可以卖下前P1164-小A买菜(动态规划,01背包)个商品 的方法数的基础上 买下P1164-小A买菜(动态规划,01背包)这件商品的方法数,直接覆盖掉 P1164-小A买菜(动态规划,01背包)
  • 所以要倒过来历遍P1164-小A买菜(动态规划,01背包),以防 P1164-小A买菜(动态规划,01背包) 被覆盖了

版权声明:本文为博主作者:T_J_J_原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/T_J_J_/article/details/135517187

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2024年4月22日
下一篇 2024年4月22日

相关推荐