问题描述
有一个整数n,将n分解成若干个不同自然数之和,问如何分解能使这些数的乘积最大,输出这个乘积m
动态规划
根据题意,对于一个整数n,必然存在一个整数x,使得从n中分解出整数x可以使其最后获得最大乘积,这要求对n-x的分解也是最优解。我们用dp[i][j]表示从整数i分解出整数j的这种情况下,能达到的最大乘积。那么dp[i][j]可以递归的定义为
d p [ i ] [ j ] = { d p [ i ] [ j ] = i i = j d p [ i ] [ j ] = max d p [ i − j ] [ k ] ∗ j j < = i 且 1 < = k < = i − j dp[i][j] = \begin{cases} dp[i][j] = i\ \ \ \ \ \ \ \ \ \ \ \ \ i = j \\ dp[i][j] = \max {dp[i-j][k] * j} \ \ \ \ \ \ j <= i 且 1<=k<=i-j\\ \end{cases} dp[i][j]={dp[i][j]=i i=jdp[i][j]=maxdp[i−j][k]∗j j<=i且1<=k<=i−j
构造一个二维数组dp,自底向上计算结果,最后通过查表得到最终结果。
对于给定的整数n,最后的最大乘积为
a n s = max d p [ n ] [ i ] 0 < = i < = n ans = \max dp[n][i] \ \ \ \ \ \ \ \ 0<=i<=n ans=maxdp[n][i] 0<=i<=n
代码和测试
#include <cstdio>
#include <iostream>
#include <cstring>
#define maxn 109
long long dp[maxn][maxn]; //dp[i][j]:从i中分解出j后,能达到的最大乘积
using namespace std;
int solve(int n)
{
/*赋初始值*/
memset(dp, 0, maxn * maxn * sizeof(long long));
for(int i = 1; i <= n; i++)
dp[i][i] = i;
/*根据递推式构造二维表*/
for(int i = 2; i <= n; i++){
for(int j = 1; j < i; j++){
for(int k = 1 ; k <= i-j; k++) //找最大值
dp[i][j] = max(dp[i][j], dp[i - j][k] * j);
}
}
/*从表中找出最大值返回*/
long long ans = 0;
for(int i = 1; i <= n; i++)
ans = max(ans, dp[n][i]);
return ans;
}
void test1()
{
int length = 1;
int expected = 1;
cout << expected << "\t\t" << solve(length) << endl;
}
void test2()
{
int length = 2;
int expected = 2;
cout << expected << "\t\t" << solve(length) << endl;
}
void test3()
{
int length = 3;
int expected = 3;
cout << expected << "\t\t" << solve(length) << endl;
}
void test4()
{
int length = 4;
int expected = 4;
cout << expected << "\t\t" << solve(length) << endl;
}
void test5()
{
int length = 5;
int expected = 6;
cout << expected << "\t\t" << solve(length) << endl;
}
void test6()
{
int length = 6;
int expected = 9;
cout << expected << "\t\t" << solve(length) << endl;
}
void test7()
{
int length = 7;
int expected = 12;
cout << expected << "\t\t" << solve(length) << endl;
}
void test8()
{
int length = 8;
int expected = 18;
cout << expected << "\t\t" << solve(length) << endl;
}
void test9()
{
int length = 9;
int expected = 27;
cout << expected << "\t\t" << solve(length) << endl;
}
void test10()
{
int length = 10;
int expected = 36;
cout << expected << "\t\t" << solve(length) << endl;
}
void test11()
{
int length = 50;
int expected = 86093442;
cout << expected << "\t" << solve(length) << endl;
}
int main()
{
cout << "excetped" << '\t' << "real" << endl;
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();
return 0;
}