洛谷 P1025 [NOIP2001 提高组] 数的划分
一. dfs
因为数据比较小,此题可以用搜索来暴力,需要注意的是:
①因为要考虑重复,所以我们划分个数采用升序,要保证后一个划分的个数要大于等于前一个划分的个数。
②为了防止TLE,要进行适当的剪枝,详情见代码。
#includeusing 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 B.当 i=j ,必然只有一种情况,即每份都只放一个,a[i][j]=1 C.当i>j , 有两种情况: ① 分好j份,不再增加新的一份,而是j份里每个都在放入一个数,即加上a[i-j][j]的分法。 ② 增加新的一份,放入一个数,即加上a[i-1][j-1]的分法。 完结撒花~#include