题意:把一个不超过16位的数字分成m份,求乘积最大值。一个例子:12345拆成两部分,1234|5、123|45 ......,但是最大值是1234 * 5 = 6170
思路:动态规划,f(i, j, t)表示数字的第i位到j位,拆成t部分的最大值。方程:f(i, j, t) = max { f(i, k, 1) * f(k+1, j, t-1) } , k = i..(j-t+1) ;
即, t份的乘积最大值,等于 最左面1份的最大值 与 其余t-1份的最大值 的最大值。-----最优性原理。决策k把问题分成两个子问题
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio>
#include<cstring>
using namespace std;
int n, m;
char num[20];
long long dp[20][20][20];
long long str_int(int i, int j){//i<=j
long long b, s;
b = 1;
s = 0;
for(int k=j; k >= i; --k){
s += (num[k] - '0') * b;
b *= 10;
}
return s;
}
void process(){
int i, j, t, k;
long long max, tmp;
for(i=1; i<=n; ++i)
for(j=i; j<=n; ++j)
dp[i][j][1] = str_int(i, j);
for(t=2; t<=m; ++t)//分成t份
for(i=1; i<=n; ++i)
for(j=i+t-1; j<=n; ++j){
max = 0;
for(k=i; j-k+1 >= t; ++k){
tmp = dp[i][k][1] * dp[k+1][j][t-1];
if(tmp > max)
max = tmp;
}
dp[i][j][t] = max;
}
}
int main(){
// freopen("in", "r", stdin);
while(scanf("%s %d", &num[1], &m) != EOF){
n = strlen(&num[1]);
process();
printf("%lld\n", dp[1][n][m]);
}
}