zoukankan      html  css  js  c++  java
  • 洛谷P1025 数的划分【dp】

    将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

    例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的。

    1,1,51,1,5;
    1,5,11,5,1;
    5,1,15,1,1.

    问有多少种不同的分法。

    输入输出格式

    输入格式:

    n,kn,k (6<n le 2006<n≤200,2 le k le 62≤k≤6)

    输出格式:

    11个整数,即不同的分法。

    输入输出样例

    输入样例#1: 复制

    7 3
    

    输出样例#1: 复制

    4
    

    说明

    四种分法为:
    1,1,51,1,5;
    1,2,41,2,4;
    1,3,31,3,3;
    2,2,32,2,3.

    思路:常用有两种做法,即dp和递归,dp的话要能推得方程dp[i][j]=dp[i-1][j-1]+dp[i-j][j];分析一下:

    1. 当i=j时,此时只能为1

    2. 当i<j时,毫无疑问为0

    3. 当i>j时,分为两种情况

    ①有1的 ②没有1的

    第一种情况,方案数为 f[i-1][x-1]

    第二种情况,方案数为 f[i-x][x] (此时 i 必须大于 x)

    所以,状态转移方程为: f[i][x]=f[i-1][x-1]+f[i-x][x]

    dfs

    关键方程dp(i, sum + i, pos + 1);,其中i为第pos(position)个选取的数,

    同时加入边界判断:

    1. n - sum >= (dv - pos)意义为剩下的至少可以组合得到n(全取1).

    2. pos == i时判断cnt+=(sum==n)? 1 : 0;(cnt表示计数)

    #include<cstdio>
    #include <iostream>
    #include<string>
    using namespace std;
    const int maxn=205;
    //const int Mod=100003;
    int dp[maxn][8];
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;++i)
            dp[i][1]=1;
        for(int i=1;i<=k;++i)
            dp[1][k]=0;
        for(int i=2;i<=n;++i)
        {
            for(int j=2;j<=k;++j)
            {
                if(i>j)
                    dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
                else
                    dp[i][j]=dp[i-1][j-1];
            }
        }
        printf("%d
    ",dp[n][k]);
        return 0;
    }
    
  • 相关阅读:
    从源码分析 XtraBackup 的备份原理
    移动端 SDK 开发经验总结及梳理
    spring boot jar包开机自启
    在Simulink中添加VeriStand支持
    java 启动脚本
    Docker容器日志管理最佳实践
    docker 日志限制或者删除
    网盘搜索
    tuple c++
    google原版:Debugging WebAssembly with modern tools
  • 原文地址:https://www.cnblogs.com/aerer/p/9930949.html
Copyright © 2011-2022 走看看