洛谷 P1025 [NOIP2001 提高组] 数的划分
一. dfs
因为数据比较小,此题可以用搜索来暴力,需要注意的是:
①因为要考虑重复,所以我们划分个数采用升序,要保证后一个划分的个数要大于等于前一个划分的个数。
②为了防止TLE,要进行适当的剪枝,详情见代码。
#include<bits/stdc++.h> using namespace std; int n,k,sum; int dfs(int kongjian,int weizhi,int floor){ if(floor==k){ if(weizhi==n) sum++; //已划分k份且数字都已划分完,分法+1 return 0; } for(int i=kongjian;(k-floor)*i+weizhi<=n;i++){ //这一步剪枝很关键,当你选择划分一份的个数(i)在最小的划分情况(即后面都划分i个)中都>n,必然无解 dfs(i,weizhi+i,floor+1); //继续搜索 } } int main(){ scanf("%d%d",&n,&k); dfs(1,0,0); //dfs(划分一份的个数,已划分到的数的位置,已划分的份数) printf("%d\n",sum); return 0; }
二 . dp
用a[i][j]表示i个数划分j份的分法数.
A.当i<j 母庸质疑,a[i][j]=0
B.当 i=j ,必然只有一种情况,即每份都只放一个,a[i][j]=1
C.当i>j , 有两种情况:
① 分好j份,不再增加新的一份,而是j份里每个都在放入一个数,即加上a[i-j][j]的分法。
② 增加新的一份,放入一个数,即加上a[i-1][j-1]的分法。
#include<bits/stdc++.h> using namespace std; int n,k,a[205][15]; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) a[i][1]=1;//只放一份,只有一种情况 for(int i=2;i<=k;i++) a[1][i]=0;//分的比总数多,无解 for(int i=2;i<=n;i++){ for(int j=2;j<=k;j++){ if(i==j){ //对应B a[i][j]=a[i-1][j-1]; }else if(i>j){ //对应C a[i][j]=a[i-1][j-1]+a[i-j][j]; }else{//对应A a[i][j]=0; } } } printf("%d\n",a[n][k]); return 0; }
完结撒花~
本文作者:南风未起
本文链接:https://www.cnblogs.com/jiangchen4122/p/15888584.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步