• 一本通网站 1440:【例题1】数的划分 及 剪枝小结


    原题  传送门

    【题目描述】

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

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

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

    问有多少种不同的分法。 输出一个整数,即不同的分法。

    【输入】

    两个整数n,k(6<n≤200,2≤k≤6),中间用单个空格隔开。

    【输出】

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

    【输入样例】

    7 3

    【输出样例】

    4

    【提示】

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

    本题就是求把数字n无序划分成k份的方案数。也就是求方程X1+X2+……Xk=n,1<=X1<=X2<=……Xk的解数。

    搜索的方法是依次枚举X1,X2,……Xk的值,然后判断,如果这样一直直接搜索,程序的运行速度是非常慢的。但由于本题的数据规模比较小,如果控制好扩展结点的上界和下界,也是能够很快得出解的。

    约束条件:

    1.由于分解数不考虑顺序,因此我们设定分解数依次递增,所以扩展点时的下界应该是不小于前一个扩展点的值,即a[i-1]<=a[i];

    2.假设我们将n已经分解成了a[1]+a[2]+……+a[i-1],则a[i]的最大值为i~k这k-i+1分平均划分,即设m=n-(a[1]+a[2]+……+a[i-1]),则a[i]<=m/(k-i+1),所以扩展点的上界是m/(k-i+1);

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int read()
    {
        char ch=getchar();
        int a=0,x=1;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') x=-x;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            a=(a<<3)+(a<<1)+(ch-'0');
            ch=getchar();
        }
        return a*x;
    }
    int n,m,a[9],s=0;
    void dfs(int x)
    {
        if(n==0) return ;       //若将n分解完,则直接返回 
        if(x==m)                //若此时分解数的个数到了m 
        {
            if(n>=a[x-1]) s++;
            return ;
        }
        for(int i=a[x-1];i<=n/(m-x+1);i++)  //从下界枚举到上界 
        {
            a[x]=i;
            n-=i;
            dfs(x+1);
            n+=i;      //回溯 
        }
     } 
     int main()
     {
         n=read();
         m=read();
         a[0]=1;        //从1开始分解 
         dfs(1);
         cout<<s<<endl;
         return 0;
     }

    对神搜的剪枝技巧进行小结:

    所谓剪枝就是通过某种判断,避免一些不必要的遍历过程,形象地说,就是减去搜索树中的某些枝条,故城剪枝。

    剪枝的原则:

    1.正确性;

    2.准确性;

    3.高效性;

    深度优先搜索的优化技巧:

    1.优化搜索顺序;

    2.排除等效冗杂;

    3.可行性剪枝;

    4.最优性剪枝;

    5.记忆化;

  • 相关阅读:
    最短路计数
    轻拍牛头(类埃式筛)
    子序列(尺取模板题)
    状压dp(洛谷:互不侵犯)
    刷题-力扣-73. 矩阵置零
    刷题-力扣-150. 逆波兰表达式求值
    刷题-力扣-300. 最长递增子序列
    刷题-力扣-1576. 替换所有的问号
    刷题-力扣-54. 螺旋矩阵
    刷题-力扣-705. 设计哈希集合
  • 原文地址:https://www.cnblogs.com/xcg123/p/10991783.html
Copyright © 2020-2023  润新知