POJ1651
Codevs1017 乘积最大 —2000年NOIP全国联赛提高组
预处理出所有数字组合。
dp[i][k] 表示前 i 个数字已经用了 k 个 乘号。
状态转移方程:dp[i][k] = max(dp[i][k], dp[j][k-1]*mul[j+1][i]);
第i个数字用了k个乘号的状态 可以从 小于i 的j 用了k-1个乘号的状态转移而来。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;
#define MAXN (100+10)
char s[MAXN];
int mul[MAXN][MAXN], dp[MAXN][MAXN];
int main()
{
int n, K;
cin >> n >> K;
scanf("%s", s+1);
for(int i = 1; i <= n; i ++)
{
for(int j = i; j <= n; j ++)
{
for(int k = i; k <= j; k ++)
{
mul[i][j] *= 10;
mul[i][j] += s[k]-'0';
}
}
}
for(int i = 1; i <= n; i ++)
dp[i][0] = mul[1][i];
for(int k = 1; k <= K; k ++)
for(int i = k+1; i <= n; i ++)
for(int j = k; j < i; j ++) // 因为↓ 所以 j < k 无意义
dp[i][k] = max(dp[i][k], dp[j][k-1]*mul[j+1][i]);
cout << dp[n][K];
return 0;
}