题解 | 砝码称重

alt

题干解析

题设给予我们6种砝码,分别个,要求我们返回这些砝码能够组成的总重种数。

算法思路

本题可以进行一些转化,我们设定我们有一个承重为i的背包,设定状态值dp[i]表示装满这个背包的方案数。由此我们能够将整个问题转化为求dp数组,最后统计dp数组种的非零值的个数然后输出即为答案。

通过以上转化,我们将问题转化为一个背包DP问题。理论上本题数据量不大,能够直接转化为0/1背包进行求解,以下内容为对其进行二进制优化后的解法,通过将总数进行二进制拆分,优化时间复杂度。

实现代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    vector<int> a(6);
    vector<int> m= {1, 2, 3, 5, 10, 20};
    int sum = 0;
    for (int i = 0; i < 6; ++i) {
        cin >> a[i];
        sum += a[i] * m[i];
    }
    // 二进制拆分优化
    vector<int> c;
    for (int i = 0; i < 6; ++i) {
        for (int j = 1; j <= a[i]; j <<= 1) {
            a[i] -= j;
            c.push_back(j * m[i]);
        }
        if (a[i]) {
            c.push_back(a[i] * m[i]);
        }
    }
    // DP
    vector<int> dp(sum + 1, 0);
    dp[0] = 1;
    for (auto i : c) {
        for (int j = sum; j >= i; --j) {
            dp[j] += dp[j - i];
        }
    }
    // 计数
    int N = 0;
    for (auto i : dp) {
        if (i) ++N;
    }
    cout << "Total=" << N - 1; // 重量为0不计入

    return 0;
}

复杂度分析

  • 时间复杂度:
  • 空间复杂度:
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务