b_dd_凑硬币进阶-最多使用k个(完全背包+算组合数)
1、2、5 三种硬币,使用 k 个,要凑成 target 共有几种方式?
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
// 1、2、5 三种硬币,只使用 k 个凑成 target 共有几种方式?
// f[i][j][k] 表示用前i种硬币,使用j个,凑成金额k的方案数
int solve(vector<int>& coins, int tg, int K) {
int n = coins.size();
int f[n+1][K+1][tg+1];
memset(f, 0, sizeof f);
for (int i = 0; i <= n; i++)
f[i][0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= K; j++)
for (int k = 0; k <= tg; k++) {
f[i][j][k] = f[i-1][j][k]; //这个转移没想明白
if (k >= coins[i-1])
// f[i][j][k] = f[i-1][j-1][k-coins[i-1]] + 1; //这样写是不对的
f[i][j][k] += f[i][j-1][k-coins[i-1]]; //这样写是不对的
}
return f[n][K][tg];
}
int main() {
vector<int> coins(3);
coins[0] = 1, coins[1] = 3, coins[2] = 5;
int target = 10, k = 2;
cout << solve(coins, target, k);
}
第一维没什么用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
const ll mod=1e9+7;
// 1、2、5 三种硬币,只使用 k 个凑成 target 共有几种方式?
// f[i][j][k] 表示用前i种硬币,使用j个,凑成金额k的方案数
int solve(vector<int>& coins, int tg, int K) {
int n = coins.size();
int f[K+1][tg+1];
memset(f, 0, sizeof f);
for (int i = 0; i <= n; i++)
f[0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= K; j++)
for (int k = coins[i-1]; k <= tg; k++) {
// f[i][j][k] = f[i-1][j-1][k-coins[i-1]] + 1; //这样写是不对的
f[j][k] += f[j-1][k-coins[i-1]]; //这样写是不对的
}
return f[K][tg];
}
int main() {
vector<int> coins(3);
coins[0] = 1, coins[1] = 2, coins[2] = 5;
int target = 8, k = 3;
cout << solve(coins, target, k);
}