最大k乘积问题。
问题描述
设I是一个n位十进制整数。如果将I划分为k段,则可得到k个整数。这k个整数的乘机称I的一个k乘积。试设计一个算法,对于给定的I和k,求出I的最大乘积。
input
第一行是n和k,第二行是整数I
2 1
15
output
最大k乘积
15
分析
cal(i,j)为n位整数I的i到j位拼成的数字,例如I=1234,cal(2,4)=234
f[i][j]
为数字cal(1,i)
,划分为j
段时的最大乘积和
j段最大乘积化为j-1段
f[i][j]=max(f[kk][j-1]*cal(kk+1,j),f[i][j]), 1<=kk<=i
列表
j \ i | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 | 1 | 12 | 123 | 1234 |
2 | 0 | 2 | 36 | 492 |
3 | 0 | 0 | 6 | 144 |
4 | 0 | 0 | 0 | 24 |
代码
#include<iostream>
#include<vector>
#include<string>
using namespace std;
#define N 50
int n,k;
string s;//整数I
int num[N];//I的每一位
int f[N][N];
//I=1234,cal(2,3)=23,cal(2,4)=234
int cal(int l,int r){
int ans=num[l];
for(int i=l+1;i<=r;i++)
ans=ans*10+num[i];
return ans;
}
int main(){
cin>>n>>k;
cin>>s;
for(int i=1;i<=n;i++)
num[i]=s[i-1]-'0';
//初始化第一列
for(int i=1;i<=n;i++){
f[i][1]=cal(1,i);
}
for(int i=1;i<=n;i++){
for(int j=2;j<=k;j++){
if(i==j)
f[i][j]=f[i-1][j-1]*cal(i,i);
else if(i<j)
f[i][j]=0;
else{
if(j!=1)
f[i][j]=0;
for(int kk=1;kk<i;kk++){
if(kk<j-1)
f[kk][j-1]=0;
f[i][j]=max(f[kk][j-1]*cal(kk+1,j),f[i][j]);//j段最大乘积化为j-1段
}
}
}
}
cout<<f[n][k]<<endl;
for(int j=1;j<=k;j++)
{
for(int i=1;i<=n;i++){
cout<<f[i][j]<<" ";
}
cout<<endl;
}
return 0;
}