• ybt1318 自然数拆分(又一手打dfs)


    ybt1318 自然数拆分

    【题目描述】

    任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。

    当n=7共14种拆分方法:

    7=1+1+1+1+1+1+1
    7=1+1+1+1+1+2
    7=1+1+1+1+3
    7=1+1+1+2+2
    7=1+1+1+4
    7=1+1+2+3
    7=1+1+5
    7=1+2+2+2
    7=1+2+4
    7=1+3+3
    7=1+6
    7=2+2+3
    7=2+5
    7=3+4
    total=14
    

    【输入】

    输入n。

    【输出】

    按字典序输出具体的方案。

    【输入样例】

    7
    

    【输出样例】

    7=1+1+1+1+1+1+1
    7=1+1+1+1+1+2
    7=1+1+1+1+3
    7=1+1+1+2+2
    7=1+1+1+4
    7=1+1+2+3
    7=1+1+5
    7=1+2+2+2
    7=1+2+4
    7=1+3+3
    7=1+6
    7=2+2+3
    7=2+5
    7=3+4
    

    【题解】

    观察样例,可以看出每个方案的加数是升序排列的

    在一开始,我把这道题想成ybt1200 分解因数的加法版本,但是分解因数只是要求输出方案数,没法输出方案,而且方案数累加过程中,是不按字典序递增的,同样不行。

    一开始走的弯路:

    如果用分解不行,为什么不把n先看做n个1,然后合并呢?(这只是个猜想,因为没看题解,只能走一步说一步)

    但是我想了想就放弃了,毕竟这个单元是搜索嘛!

    正解

    后来我就又想到可以借鉴爬楼梯的思路(爬楼梯是按照最后一步迈几级分类),把情况按照当前的第一个加数(最小的)分类:先讨论第一个加数是1的情况,全部输出后在讨论第一个加数是2的情况······以此类推,最后一直到第一加数是n/2(向下取整)(因为加数最少两个,而每个加数递增排列,所以最小加数最大为n/2)

    这样,就这问题分解了。最小加数为1时,输出1,然后按n=n-1的情况处理。

    边界条件就是当n=1时,分解后就是1。

    打了一会代码,发现越来越迷茫,一看书上的题解,发现算法没毛病,只是输出有问题,那就继续自己打!

    #include<iostream>
    using namespace std;
    int n,ans[10005];
    void dfs(int x,int y) {//x表示还没有分配的n的数字,y表示当前所决定的最小加数位置 
    	if(x==1){//只剩一了,不能分解,直接输出(当然,这种情况一个测试点只会执行一次,因为这里1是最后一个加数也就是最大的加数,这种情况只有n个加数均为1才会执行)
    		ans[y]=1;//将1作为当前最小加数也是最后一个加数
    		cout<<n<<"="<<ans[1];//输出开头和第一个加数
    		for(int k=2; k<=y ;k++) {
    			cout<<"+"<<ans[k];//输出后面的加数
    		} 
    		cout<<endl;//方案输出完毕
    	}
    	else{
    		for(int j=ans[y-1];j<=x/2;j++) {
    			ans[y]=j;//给当前位赋值
    			dfs(x-j,y+1);//再分别以各个j为第y
    		}
    		ans[y]=x;//也可以选择不分解直接以第y位的x为最后一位
    		cout<<n<<"="<<ans[1];//输出
    		for(int k=2;k<=y;k++) {
    			cout<<"+"<<ans[k];
    		}
    		cout<<endl;
    	}
    	return;
    }
    int main() {
    	cin>>n;
    	for(int i=1;i<=n/2;i++) {//枚举不同的i,也就是首位最小加数
    		ans[1]=i;//首位赋值
    		dfs(n-i,2);//讨论后面的位
    	}
    	return 0;
    }
    

    这题也是一道dfs,做题时要注意按照输出顺序来决定算法。

  • 相关阅读:
    转换上午下午 时间
    Canvas
    DOS Card (线段树)(hud杭电多校)
    ShuanQ (取模的小知识)(杭电多校)
    Painting Game (博弈论)
    Two Permutations (DP搜索的方式) (2022杭电多校3)
    Slayers Come (区间覆盖种类数(dp+线段树)+ st表+二分,或者线段树) (2022杭电多校2)
    copy (倒叙离线+bitset+^特性) (hud 2022多校 2)
    Static Query on Tree (述链剖分+线段树)(2022杭电多校)
    Fast Bubble Sort (单调zai+倍增) (2022杭电多校10)
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/12236653.html
Copyright © 2020-2023  润新知