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);
}

https://leetcode-cn.com/circle/discuss/fMOTe9/

posted @ 2021-06-13 20:19  童年の波鞋  阅读(79)  评论(0编辑  收藏  举报