题目:自然数N分解为n个自然数的和,求这n个数的乘积最大值
分析:最优问题,可以用动态规划求解
1、描述最优解结构
N = a1 + a2 + ... + an;
M = a1 * a2 * ... * an;
求M的最大值
考虑到N = a + b,而a与b又可以分解为另外几个和为a或b的数的积,因此对于确定的N = a + b,有一个最优解M(N) = M(a)*M(N-a)。而a又有1到N/2种取值,所以有一般最优解M(N) = max{M(a) + M(N - a)}(a < N/2)。而对于1、2、3、4、5等的M值列一个表,就可以得到N<=4时,M(N) = N。于是有下列递归定义。
2、递归定义最优解

3、按自底向上的方式计算最优解
源码:
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
#define SIZE 1000
unsigned long m[SIZE], t[SIZE];
//m[i]存放和为i的数的乘积最大值,t[i]存放使m[i]为最大时,将i划分为2部分的j的值,即m[i]=m[j]*m[i-j]最大时j的值
void mt(int a)
{
int i, j;
for (i = 0; i < SIZE; i++) //m、t初始化
{
m[i] = i;
t[i] = i;
}
for (i = 4; i <= a; i++) //按自底向上来得到m与t的值
{
for (j = 2; j <= i/2; j++)
{
if (m[i] <= m[j] * m[i - j])
{
m[i] = m[j] * m[i - j];
t[i] = j;
}
}
}
}
void printt(int a) //打印和为a,积最大的所有数
{
int k;
k = t[a]; //k为a的第一次分解值
if (k == t[k]) //不能再分的时候,输出k
{
cout<<k;
}
else //继续分解,打印出和为k,积最大的所有数
{
printt(k);
}
if(a - k > 0) //打印出和为a - k,积最大的所有数
{
cout<<" * ";
printt(a - k);
}
}
void main()
{
int n;
cout<<"input a number(<= 62) "; //输入小于62的数。由于unsigned long只能表示到2的31次方,只能存储小于62的M值
cin>>n;
mt(n); //计算m和t
cout<<m[n]<<" = ";
printt(n); //打印
cout<<endl;
}