赞
踩
#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; }
l i n e : 11 line :11 line:11 为所有花费 0 元的商品的方法赋值为 1; 因为花费0元的方法,有且仅有一种,那就是都不买
l i n e : 13 − 14 line:13-14 line:13−14 两次循环,外循环为商品的数目,内循环为 花费的钱 ,即表示 每 i : ( 1 → n ) i:(1\to n) i:(1→n) 件商品 花费 j : ( 1 → m ) j:(1 \to m) j:(1→m) 元 的方法数, 先历遍商品数.(动态规划的方程为$ dp[i][j] += dp[i - 1][j - a[i]]$ 就是通过 i − 1 i-1 i−1 的数目推出 i i i 的数目,所以先历遍商品数)
if (j >= a[i]) {
dp[i][j] += dp[i - 1][j - a[i]];
}
dp[i][j] += dp[i - 1][j];
其中 d p [ i ] [ j ] dp[ i ][ j ] dp[i][j] 表示前 i i i 个商品花费 $ j $ 元的方法数.
d p [ i ] [ j ] dp[i][j] dp[i][j]一共有两种情况:
因为求的是方法,所以两种情况都要加上, 其中不买 i i i 这件商品 这种情况一定存在
最后输出 d p [ n ] [ m ] dp[n][m] dp[n][m] ,即一共 n n n 件商品 花费 m元的方法
为何可以优化?:
每次循环只用到了 i i i 的上一个 i − 1 i-1 i−1
所以由 d p [ i ] [ j ] dp[i][j] dp[i][j] 可以变为 d p [ j ] dp[j] dp[j]
#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; }
l i n e : 15 line:15 line:15 一维的 d p [ j ] + = d p [ j − a [ i ] ] dp[j] += dp[j - a[i]] dp[j]+=dp[j−a[i]] 对比 二维的 d p [ i ] [ j ] + = d p [ i − 1 ] [ j − a [ i ] ] dp[i] [j] += dp[i - 1] [j - a[i]] dp[i][j]+=dp[i−1][j−a[i]]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。