栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【算法基础】计数类DP AcWing 900. 整数划分 (闫氏dp分析法)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【算法基础】计数类DP AcWing 900. 整数划分 (闫氏dp分析法)


题目描述

链接
给定一个正整数n,问有多少种方案使得n=x1+x2+…+xn,因此不需要考虑顺序。

思路1 (完全背包)


5的所有情况↓

闫氏DP分析法:
状态表示: f [ i ] [ j ] f[i][j] f[i][j] 表示所有1~i中选,且体积恰好是j的选法的数量
属性:COUNT
状态计算:
推导过程↓

其中s表示选i的个数
数学归纳法
得出状态表示: f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] f[i][j] = f[i - 1][j] + f[i][j - 1] f[i][j]=f[i−1][j]+f[i][j−1]
根据完全背包的思路可以优化为一维:
f [ j ] = f [ j ] + f [ j − i ] f[j] = f[j] + f[j - i] f[j]=f[j]+f[j−i]

C++代码
#include 
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n,f[N];
int main () {
  cin >> n;
  f[0] = 1;
  for(int i = 1;i <= n; i ++) {//从小到大开始枚举 
    for(int j = i; j <= n; j ++) {//需要从1 开始
      f[j] = (f[j] + f[j - i]) % mod;
    }
  }
  cout << f[n] << endl;
  return 0;
}
思路2


由于是按位数计算的,最后结果需要把每个区间都加上

C++ 代码
#include 
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n,f[N][N];
int main () {
  cin >> n;
  f[0][0] = 1;//初始化
  for(int i = 1; i <= n; i ++) {//枚举总和
    for(int j = 1; j <= i; j ++) {// 枚举个数到 i (全部用1表示)
      f[i][j] = (f[i - 1][j - 1] + f[i - j][j]) % mod;//划分为最小值是1 和 >1
    }
  }
  int ans = 0;
  for(int i = 1; i <= n; i ++) {
    ans = (ans + f[n][i]) % mod;
  }
  cout << ans << endl;
  return 0;
}
感谢阅读
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847355.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号