最大k乘积
问题描述
设I 是一个n 位十进制整数。如果将I 划分为k 段,则可得到k 个整数。这k 个整数的乘积称为I 的一个k 乘积。对于给定的I 、n和k,试设计一个算法,编程计算I 的最大k 乘积。
Intput | output |
---|---|
2 1 | 15 |
15 |
问题分析
前i位最大j乘积记作dp[i][j],第i位到低j位的十进制整数记作r[i][j]。
dp[i][j]即前 i 位分成 j 段的最大乘积(最优值)。
- 最优子结构证明:
dp[i][j]把最后一段拿掉后为dp[k][j-1](k为i-后一段的位数)*r[k+1][i],若dp[k][j-1]不是最优,有dp’[k][j-1]>dp[k][j-1],两边乘r[k+1][i]即dp’[k][j-1]*r[k+1][i]>dp[k][j-1]*r[k+1][i]即dp’[i][j]>dp[i][j]与原命题不符。 - 递归定义
dp[i][j]=max(dp[k][j-1]*r[k+1][i])
j-1<=k<=i;k表示去掉最后一段的位数 - 最优解
用递归的方式求,前i位数最大j乘积最后一位乘号的位置记作dp_s[i][j];
代码部分
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 110
int r[MAX][MAX];
int dp[MAX][MAX];
int dp_s[MAX][MAX];
int traceback(int n,int k)
{
if (k < 1) return 0;
traceback(dp_s[n][k], k - 1);
cout << dp_s[n][k] << " ";
}
void matrix(int n,long long int count)
{
for (int i = n; i >= 1; i--)
{
r[i][i] = count % 10;
count /= 10;
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
r[i][j] = r[i][j - 1] * 10 + r[j][j];
}
}
}
int main()
{
int n, k;
long long int count;
cout<<"输入n位数和分为k段和这个数count:";
cin >> n >> k >> count;
matrix(n, count);//算r[i][j] 从第i位到第j位;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
if (j == 1)
{
dp[i][j] = r[1][i];
dp_s[i][j] = i;
}
for (int k = j - 1; k <= i; k++)
{
dp[i][j] = max(dp[i][j], dp[k][j - 1] * r[k + 1][i]);
dp_s[i][j] = dp[i][j] > dp[k][j - 1] * r[k + 1][i] ? dp_s[i][j] : k;
}
}
}
cout<<endl<<"最优值是:" ;
cout << dp[n][k];
cout<<endl<<"最优解是:" ;
traceback(n, k);
system("PAUSE");
return 0;
}