zoukankan      html  css  js  c++  java
  • 【做题笔记】P1025数的划分

    可以说是这个题的一个变种,然而直接成了黄题是什么鬼(((

    注:上面那篇blog里对于 dfs 的讲解不是很到位,所以这次就当是修一下锅www/wq


    首先,我们发现这个玩意和 dfs 的搞法一毛一样,所以果断考虑 dfs !

    如果直接去遍历所有的状态,不仅耗时,而且难以辨别重复。

    那么我们发现,按照题目的要求,也就是让我们找到有多少个本质不同的组合(即构成组合的数字不同)。

    那么我们发现:在一种本质相同的组合中,一定有一种组合保证升序排列

    例如:我们现在要把 10 分成 5 份,那么对于一种本质相同的排列:

    2 1 7
    2 7 1
    7 2 1
    7 1 2
    1 2 7 //升序
    ......
    

    那么这个本质相同的组合中升序排列就是1 2 7这一种。

    由于我们只需要知道有所少个本质不同的组合,所以我们只要找到一个本质相同的组合中升序排列的组合即可!

    构造

    如何构造一组升序排列?

    如果我们在递归的过程中记录一个 start 参数表示我们在上一层递归中选的数,那么只要任选一个 (i) ,使得 (startleq i) 即可(注意到可以不是单调递增的,i.e. 允许构造出的序列存在重复值)!

    那么只要遍历所有的 (i(startleq i leq n)) ,然后递归即可。

    参考代码(60分):

    #include <cstdio> 
    #include <algorithm>
    
    int n, k, ans;
    
    void dfs(int start, int num, int x) {
    //num表示当前的序列之和,x表示当前有x个数在序列里
        if(x==k) { 
            if(num==n)
                ++ans;
            return ; 
        } 
        for(int i=start;i<=n;i++) 
            dfs(i, num+i, x+1);
    } 
    
    int main(void) {
        scanf("%d%d", &n, &k);
    
        dfs(1, 0, 0);
    
        printf("%d
    ", ans);
    
        return 0;
    }
    

    剪枝

    考虑如何通过剪枝优化。

    剪枝的核心思想是排除当前和当前之后根本没有可能满足条件的解。那么我们发现,若当前序列中的元素总和 (x) 加上现在尝试的 (i) 已经大于我们要拆分的 (n) 了,那么就可以果断退出(因为后面的 (i) 是越来越大的)!

    于是有AC代码:

    #include <cstdio> 
    #include <algorithm>
    
    int n, k, ans;
    
    void dfs(int start, int num, int x) {
        if(x==k) { 
            if(num==n)
                ++ans;
            return ; 
        } 
        for(int i=start;num+i<=n;i++) 
            dfs(i, num+i, x+1);
    } 
    
    int main(void) {
        scanf("%d%d", &n, &k);
    
        dfs(1, 0, 0);
    
        printf("%d
    ", ans);
    
        return 0;
    }
    
  • 相关阅读:
    《大型网站技术架构》读后感
    质量属性
    课堂作业02
    课堂作业01
    《软件构架实践》读后感06
    《软件构架实践》读后感05
    Storm系列三: Storm消息可靠性保障
    Storm系列二: Storm拓扑设计
    Storm系列一: Storm初步
    网络层协议
  • 原文地址:https://www.cnblogs.com/BlueInRed/p/12617587.html
Copyright © 2011-2022 走看看