您的位置:首页 > 其它

给定一个正整数n,将其分成m段,每段为n1,n2,...,nm,求怎么划分使得n1*n2*...*nm最大

2014-10-08 21:17 471 查看
题目:自然数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
<<" = ";
printt(n);                        //打印
cout<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐