# 简单整数规划问题(递归和动态规划)
### 前言
哈喽大家好,欢迎来到我的个人公众号~创建这个公众号的目的呢,是为了记录平时的所学所写,也是对所学知识的一次巩固,同时还能督促自己学习。之前也有写过一些东西,不过是在[我的CSDN](https://my.csdn.net/)上. BY THE WAY, 我个人对机器学习比较感兴趣,如果大家有什么好的想法也可以与我分享哟~让我们开始吧。
___
本周算法课上老师留了一个作业,要求用动态规划的方法去求解下面这样一个问题:
>【问题描述】将正整数n表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。正整数n的这种表示称为正整数n的划分。正整数n的不同的划分个数称为正整数n的划分数。
输入
标准的输入包含若干组测试数据。每组测试数据是一个整数N(0 < N <= 50)。
【输出】
对于每组测试数据,输出N的划分数。
样例输入
5
6
7
【样例输出】
7
11
15
【提示】
5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1
### Solution:
这题挺简单的,对吧?观察上面的提示,从左到右,分解的式子中,最大的数为5,4,3,2,1.是的,只要按照它分解的数字中最大的那个数从大到小排列(即划分中最大的整数从大到小排列),依次求解就OK了。
这明显是一个递归求解的问题,我们假设递归函数签名为`int f(int m,int n)`,于是可以将原问题大致分为有两种情况:
* 划分中包含m
* 划分中不包含m
举个栗子,如f(5,4),如果划分中包含4,也就相当于剩下了1还没划分,我们再去划分1即可;
如果不包含4,那么就令m=m-1, 即f(n,m)=f(n-m,m)+f(n,m-1)。由于不会出现负数划分,所以可能出现f(n-m,m)中,第一个参数比第二个小的情况,简单地令两个参数都为第一个即可
当然,还有很重要的一点,递归的边界是什么?So easy,当m、n任意一个是1,那肯定只有一种划分情况;当划分中的最大数等于本身时,也只有一种情况。
### 递归代码
“`c++
int f(int n,int m)
{
// 参数n为要划分的目的数,m为划分中的最大整数
if (n == 1 || m == 1) return 1;
if (n == m)
return f(n, m – 1) + 1; // 这里的1代表{n}这个自身划分
if (n < m)
return f(n, n);
else
{
return f(n – m, m) + f(n, m – 1);
}
}
“`
### 稍加思索
稍微看一眼我们就能发现,这个算法的效率并不高,不信可以跑个f(100,100)试试。能不能有别的方法呢?答案是肯定的——动态规划。
动态规划是一种自底向上的算法,而递归是自顶向下的。递归的时候总是要将原问题分解成子问题,子问题中的变量等信息存在堆栈中,如果它要求的下一个问题中包含了我们已经求解出的子问题,递归算法会存在一个重复计算子问题的情况;
而动态规划则是基于已经求好的子问题去逐步逐步求解顶层问题,而且调用子问题是在常数时间复杂度内完成的。其实问题分解的思路,递归和动态规划是完全一样的,个人认为只是人为地运用一些办法,提高问题求解的速度。
### 动态规划代码
“`c++
// 简单整数划分问题,动态规划算法
int DP_f(int n)
{
int a[MAX_SIZE + 1][MAX_SIZE + 1] = { 0 }; // a中存放的是f(row,col)
// 所有f(r,1)=1
for (int i = 1;i <= n;i++)
{
a[i][1] = 1;
}
// 所有f(1,c)=1
for (int j = 1;j <= n;j++)
{
a[1][j] = 1;
}
// 自底向上求解
for (int i = 2;i <= n;i++)
{
for (int j = 2;j <= n;j++)
{
if (i == j)
a[i][j] = a[i][j – 1] + 1;
else if (i < j)
a[i][j] = a[i][i];
else
a[i][j] = a[i – j][j] + a[i][j – 1];
}
}
return a[n][n];
}
“`
先讲到这里,来只柴犬放松一下吧。
<img src=”https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1523794723672&di=9c6249afcef0420554cca4587d2eba50&imgtype=0&src=http%3A%2F%2Fwx3.sinaimg.cn%2Flarge%2Fc0788b86gy1fi1y8f20jzj20qo0zk124.jpg” width=”35%” height=”35%” />