问题描述:
将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整数n的这种表示称为正整数n的划分。
问题1:
输出整数n的所有可能的划分,如:
输入:6
输出: 5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
我的思路:这种问题已经遇到过很多了,递归搜索所有可能的情况,同时为了记录下每一步的情况,那么就要用到一个数组mark来存储每一步的数,然后递归同时要传递递归的深度k。还有个问题就是递归下一个数的时候,因为是递减的排列的。所以我们还必须记录下上一个的数,然后下一个数必须小于或者等于上一个数。最后递归函数还有有个参数记录当前的长度,来判断是否能够组成我们想要的长度,不能的话就回溯,继续往下一个数去尝试。OK!
代码:
//整数划分问题 #include <stdio.h>int mark[10]; int n;void Divid(int now,int k,int prio) {//now记录当前长度,k记录深度,prio记录前一个的值。int i;if(now > n) return; //不合适,返回。if(now == n){for(i = 0; i < k-1; i++)printf("%d+",mark[i]);printf("%d\n",mark[i]);}else{for(i = prio; i > 0; i--){if(i <= prio) //必须必前一个要小 {mark[k]=i;now+=i;Divid(now,k+1,i);now-=i;}}}}int main() {scanf("%d",&n);Divid(0,0,n-1);return 0; }
2013/5/29 14:17
问题2:求正整数n的不同划分个数,将最大数n1不大m的划分记住做q(n,m),叫做n的m划分。
输入:n m
输出:n的m划分的总个数。
我的思路:首先要找出递归的公式来,首先分析几种简单的情况,n==1||m==1可以直接得出结果为1;而当n<m时,可以直接求出q(n,n);当n=m时,因为对于n本身只有一种情况,即n,所有可以直接用1+q(n,n-1)来求。最后当n>m时,可以用q(n,m-1)+q(n-m,m),其中q(n-m,m表示的时当m固定后,求剩下可能的情况。参考下图:
代码:
//求整数划分的个数 #include <stdio.h>int Divid(int n, int m) {if (n == 1 || m == 1) return 1; //必须是或if (n < m) return Divid(n,n);if (n == m) return 1 + Divid(n,n-1);return Divid(n,m-1) + Divid(n-m,m); }int main() {int n,m;scanf("%d%d",&n,&m);printf("%d\n",Divid(n,m));return 0; }
2013/5/29 14:35