简单整数规划问题(递归和动态规划)

7人阅读 评论(0) 收藏 举报
# 简单整数规划问题(递归和动态规划)




### 前言
哈喽大家好,欢迎来到我的个人公众号~创建这个公众号的目的呢,是为了记录平时的所学所写,也是对所学知识的一次巩固,同时还能督促自己学习。之前也有写过一些东西,不过是在[我的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%" />





查看评论

动态规划解决整数划分的问题

前几天去华为做机试,遇到一个整数划分的问题,题目是:现有1,2,5,10,20,50,100 元这几种钱币,问给定n元能有多少种分配方式。例如n=4时,有1+1+1+1  ,1+2+1 , 2+2 三...
  • sxiaobei
  • sxiaobei
  • 2015-07-08 01:00:34
  • 1469

Python 动态规划 解决0-1背包问题

参考:http://www.tuicool.com/articles/Fji2Qb;这个博客的在输出选择的物品时有错误!!!运行环境python2.x 代码如下: #n-供选择的物品个数,c-物品...
  • baoyan2015
  • baoyan2015
  • 2016-10-11 15:59:34
  • 2108

整数规划-求解方法整理

对于规划类问题的求解方法进行梳理,单解类解法指的是在搜索过程中维持单一解,种群类解法,在搜索过程中维持多个解。...
  • qq_27755195
  • qq_27755195
  • 2017-03-13 17:18:23
  • 1243

从一个小例子来初步认识递归,迭代,动态规划。

问题:有n步台阶,一次只能上1步或者2步,共有多少种走法? 思路: a 递归 步骤1:找到走完前n步台阶和前n-1步台阶之间的关系。 为了走上n步台阶,只有两种方法:从n-1步台阶爬1步走...
  • feigegegegegegegeg
  • feigegegegegegegeg
  • 2016-09-27 11:05:58
  • 1332

数模整数规划实例

非线性规划习题 之前的非线性规划的练习题题目
  • qq_34861102
  • qq_34861102
  • 2017-08-06 21:48:51
  • 774

整数规划问题求解算法

前言:通过JavaScript实现整数规划问题。 整数规划 //说明: //1. 约束条件必须全部转化为小于等于 //...
  • m0_37568521
  • m0_37568521
  • 2017-12-10 15:48:10
  • 366

活动选择问题(贪心算法vs动态规划)

活动选择问题贪心算法vs动态规划 基础知识 1-1动态规划 1-2贪心算法 1-3贪心算法vs动态规划 活动选择问题描述 活动选择问题最优子结构 活动选择问题算法设计4-1贪心算法之选择最早结束活动 ...
  • ii1245712564
  • ii1245712564
  • 2015-05-01 16:25:46
  • 2735

暴力递归转动态规划详解

以一个题目为例: 一排有N个位置,一个机器人在最开始停留在P位置上,如果P==0,下一分钟机器人一定向右移动到1位置,如果P=N-1,下一分钟机器人一定向左移动到N-2位置。如果P在0到N-1之间,...
  • grave2015
  • grave2015
  • 2017-08-24 12:08:35
  • 447

为什么0-1背包问题是NP完全问题,但该问题还有动态规划的解法?

一个NP完全问题,如果能找到它的多项式时间解
  • jim7424994
  • jim7424994
  • 2014-10-09 11:03:22
  • 6119

浅析静态规划和动态规划

什么是动态规划? 例子:最短路径问题。 下图中,连接两个节点的线段上标注着节点间的距离,请问A到D点的最短距离是多少? 静态规划 有一个很简单的思路,穷举所有可能的途径,从中选择最...
  • quicmous
  • quicmous
  • 2017-03-19 18:26:32
  • 1287
    个人资料
    等级:
    访问量: 915
    积分: 169
    排名: 109万+
    文章分类