zoukankan      html  css  js  c++  java
  • 蓝桥---数的划分(DFS、DP)

    https://www.luogu.com.cn/problem/P1025

    题目描述

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

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

    1,1,5;
    1,5,1;
    5,1,1.

    问有多少种不同的分法。

    输入格式

    n,k (6<n200,2k6)

    输出格式

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

    输入输出样例

    输入 
    7 3
    输出
    4

    说明/提示

    四种分法为:
    1,1,5;
    1,2,4;
    1,3,3;
    2,2,3.

    解法一(DFS):

    DFS算是比较容易想到的,但需要剪枝。

    void DFS(int sum,int step,int k)

    k 表示上一份分了多少个,这次就从k个开始分,sum表示到目前为止一共分了多少个,step表示到目前为止一共分了多少份。

    由于方案数不能相同,所以枚举的个数要保持递增(或递减),我们可以进行重复性剪枝,记录k(上一份分了多少个),这次就从k个开始分起。

    同时我们还要进行可行性剪枝,每次只要i从k枚举到i*(m - step) <= n-sum 就可以了。

    因为下一份分的值不能比当前的i小,假设以后每份都分i,那么如果i*(m - step) > n-sum,则说明剩余的值不够分了,当前的i就不可行了,不需要继续DFS了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <sstream>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 const int mod=1e9+7;
    16 const int maxn=1e4+10;
    17 using namespace std;
    18 
    19 int n,m;
    20 int ans;
    21 
    22 void DFS(int sum,int step,int k)//k表示上一份分到了多少个,重复性剪枝 
    23 {
    24     if(step==m)
    25     {
    26         if(sum==n) ans++;
    27         return ;
    28     }
    29     for(int i=k;i*(m-step)<=n-sum;i++)//可行性剪枝 
    30         DFS(sum+i,step+1,i);
    31 }
    32 
    33 int main()
    34 {
    35     #ifdef DEBUG
    36     freopen("sample.txt","r",stdin);
    37     #endif
    38     
    39     scanf("%d %d",&n,&m);
    40     DFS(0,0,1);
    41     printf("%d
    ",ans);
    42     
    43     return 0;
    44 }

    解法二(DP):

    dp[ i ][ j ]表示将整数 i 划分为 j 份 的方案数。

    首先,如果拿到一个整数 i ,因为题目中要求每份不能为空,因此必须先拿出 j 个数位将 j 份分别放上1,此时剩下 i - j个数。

    那么剩下的数如何处理呢?可以将其全部分到一份当中(dp[ i-j ][1]),也可以分到两份中(dp[ i-j ][2]),...,也可以分到 j 份中(dp[ i-j ][ j ]),将每一种分法全部加起来,和即为dp[ i ][ j ]。

    不过这个式子看起来并不简洁,为了求得一个简洁的式子,我们再求一个dp[i-1][j-1],

     

    比较上面两个式子可得,

     

    上式对应两种情况:

    1.有一份只分了一个1,剩下的 i-1 要分成 j-1 份,对应dp[ i-1 ][ j-1 ]。
    2.每一份的值都大于1,也就是先在j份中,每一份都放一个1,然后还剩下 i-j 个,再把这 i-j 个再分给这 j 份,对应dp[ i-j ][ j ]。(此时 i 必须大于 j )

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <sstream>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 const int mod=1e9+7;
    16 const int maxn=1e4+10;
    17 using namespace std;
    18 
    19 int dp[205][10];
    20 
    21 int main()
    22 {
    23     #ifdef DEBUG
    24     freopen("sample.txt","r",stdin);
    25     #endif
    26     
    27     int n,m;
    28     scanf("%d %d",&n,&m);
    29     for(int i=1;i<=n;i++)
    30     {
    31         dp[i][1]=1;
    32         for(int j=2;j<=m;j++)
    33         {
    34             if(i==j) dp[i][j]=1;
    35             else if(i>j) dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
    36         }
    37     }
    38     printf("%d
    ",dp[n][m]);
    39     
    40     return 0;
    41 }

    -

  • 相关阅读:
    hadoop集群委任和解除节点
    hadoop参数
    HDFS启动及读写过程(读书笔记)
    hadoop QJM高可用原理
    十七、S3C2440裸机—IIC 接口
    十六、S3C2440裸机—UART
    十五、S3C2440裸机—系统时钟和定时器
    十四、s3c2440裸机—中断控制器
    四、NAND Flash
    二、存储管理器--SDRAM
  • 原文地址:https://www.cnblogs.com/jiamian/p/12275461.html
Copyright © 2011-2022 走看看