JOJ 2412 Divide the finger yongmou

题意:把一个不超过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把问题分成两个子问题

代码:

代码
#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]);
}
}

原文地址:https://www.cnblogs.com/liyongmou/p/1775439.html