递归问题(整数规划)

递归——整数规划问题

问题描述:

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整数n的这种表示称为正整数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

问题1:

求正整数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;
}

问题2:

输出整数n的所有可能的划分

思路:

递归搜索所有可能的情况,同时为了记录下每一步的情况,那么就要用到一个数组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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值