zoukankan      html  css  js  c++  java
  • AcWing 900. 整数划分

    题目传送门

    一、解题思路

    把整数\(n\)看成一个容量为\(n\)的背包,有\(n\)种物品,物品的体积分别是\(1-n\),我们要求的是恰好装满背包的方案数(计数),每种物品可以用无限次,所以可以看成是一个完全背包。

    先考虑二维的状态描述方法:

    \(f[i,j]\):从前\(i\)中选,总和是\(j\)的选法,值就是方案数量。

    (1)第\(i\)个物品选择了\(0\)
    表达式:\(f[i-1,j]\) ,含义:在前\(i\)个物品中选择,结果现在第\(i\)个物品选择了\(0\)个,就是说这\(j\)个体积都是前\(i-1\)贡献的。

    (2)第\(i\)个物品选择了\(1\)
    表达式:\(f[i-1,j-1 * i]\) 含义:在前\(i\)个物品中选择,结果现在第\(i\)个物品选择了\(1\)个,就是说这 \(j-1*i\) 个体积都是前\(i-1\)贡献的。

    (3)第\(i\)个物品选择了2个
    \(f[i-1,j-2*i]\)

    ...
    (4)第\(i\)个物品选择了s个
    \(f[i-1,j-s*i]\)

    初值问题

    求最大值时,当都不选时,价值显然是 \(0\)

    求方案数时,当都不选时,方案数是 \(1\)

    即:

    for (int i = 0; i <= n; i ++) f[i][0] = 1;
    

    二、二维实现代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    const int MOD = 1e9 + 7;
    int n;
    int f[N][N];
    
    int main() {
        //优化输入
        ios::sync_with_stdio(false);
        cin >> n;
        //DP初始化
        for (int i = 0; i <= n; i++) f[i][0] = 1;
    
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= n; j++) {//剩余的背包容量
                //可以装的下当前数字
                if (j >= i) {
                    //放弃当前数字
                    f[i][j] = f[i - 1][j] % MOD;
                    //选择当前数字
                    f[i][j] = (f[i - 1][j] + f[i][j - i]) % MOD;
                }
                //装不下当前数字,只能放弃
                else f[i][j] = f[i - 1][j] % MOD;
            }
        printf("%d", f[n][n]);
        return 0;
    }
    
    

    三、一维实现代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    const int MOD = 1e9 + 7;
    int f[N];
    int n;
    
    int main() {
        //优化输入
        ios::sync_with_stdio(false);
        cin >> n;
        f[0] = 1; // 容量为0时,前 i 个物品全不选也是一种方案
        for (int i = 1; i <= n; i++)
            for (int j = i; j <= n; j++)  //完全背包从小到大,01背包从大到小
                f[j] = (f[j] + f[j - i]) % MOD;
        printf("%d", f[n]);
        return 0;
    }
    
  • 相关阅读:
    SQL server 语言基础
    存储过程练习
    触发器
    存储过程
    时间日期函数,类型转化,子查询,分页查询
    数学函数,字符串函数
    用 CREATE TABLE 命令建立表的结构
    结构体,枚举类型
    函数练习
    集合以及特殊集合
  • 原文地址:https://www.cnblogs.com/littlehb/p/15457657.html
Copyright © 2011-2022 走看看