zoukankan      html  css  js  c++  java
  • AcWing 278. 数字组合

    题目传送门
    【总结】背包问题的至多/恰好/至少

    一、题目解析

    题目描述
    给定 \(n\) 个正整数:\(a_1,a_2,⋯,a_n\)

    从中选出若干个数,使得他们的和为 \(m\)

    求最终的 方案数

    分析
    对于本题我们可以把每个 正整数 看作是一个 物品

    正整数 的值就是 物品体积

    我们方案选择的 目标 是最终 体积 恰好\(m\) 时的 方案数

    于是本题就变成了** 01背包求解方案数** 的问题了

    闫氏DP分析法
    初始状态:f[0][0]

    目标状态:f[n][m]

    时间复杂度:\(O(n×m)\)

    二、二维实现代码

    #include <bits/stdc++.h>
    
    using namespace std;
    /**
    二维数组+动态规划
    状态转移方程:
    1. 不选i:f[i][j] = f[i-1][j]
    2. 选i: f[i][j] = f[i-1][j-v[i]]
    所以总的方案数就1和2的和,注意:因为体积为0时,即j=0时,是存在一种方案的:f[0][0] = 1
    */
    const int N = 110;
    const int M = 10010;
    int n, m;
    int a[N];
    int f[N][M];
    
    int main() {
        cin >> n >> m;
        f[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            for (int j = 0; j <= m; j++) {
                //不管能不能选,都可以从上一个状态继承过来
                f[i][j] = f[i - 1][j];
                //如果可选,还要增加另一些状态的方案数
                if (j >= a[i]) f[i][j] += f[i - 1][j - a[i]];
            }
        }
        //输出结果
        printf("%d", f[n][m]);
        return 0;
    }
    

    三、一维实现代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 10010;
    
    int n, m;
    int a[N];
    int f[N];//在前i个物品,体积是j的情况下,恰好装满的方案数
    
    int main() {
        cin >> n >> m;
        //体积恰好j, f[0]=1, 其余是0
        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            for (int j = m; j >= a[i]; j--)
                f[j] += f[j - a[i]];
        }
        printf("%d", f[m]);
        return 0;
    }
    
  • 相关阅读:
    SpringBoot dubbo
    springboot security 安全
    SpringBoot 异步 定时任务 邮件
    elastic search book [ ElasticSearch book es book]
    SpringBoot amqp MQ RabbitMQ
    为Nexus配置阿里云代理仓库【转】
    PLSQL表乱码
    hibernate注解的包
    Spring的refresh()方法相关异常
    spring3.1.1的各个jar作用
  • 原文地址:https://www.cnblogs.com/littlehb/p/15666824.html
Copyright © 2011-2022 走看看