NYOJ 746 整数划分(四) (区间DP)
解决问题:
给出一个长度为n的数,要在其中加上m-1个乘号,分成m段,使m段的乘积最大。
解决办法:
首先预处理出: 不划分,其各个区间的值
dp[i][j] 代表: 前i位数(即区间1-i),在划分成j段后的最大乘积。
初始化: dp[i][1]: 不划分(即划分成1段)的时候,其值等于qujian[1][i]。
递推式:
dp[i][j] = dp[k][j-1]*qujian[k+1][i]。 (k < i)
Ac 代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int N = 25;
typedef long long LL;
const int INF=0x3f3f3f3f;
char s[N];
int a[N];
long long qujian[N][N];
int m;
void init()
{
int len = strlen(s);
for(int i = 0; i < len; i++)
a[i+1] = s[i]-'0';
for(int i = 1; i <= len ; i++)
{
long long sum = 0;
for(int j = i; j <= len; j++)
{
sum = sum*10+a[j];
qujian[i][j] = sum;
}
}
}
long long dp[N][N]; // dp[i][j]表示前(i+1)个数字被划分成j段最大的乘积
void slove()
{
int len = strlen(s);
memset(dp,0,sizeof(dp));
for(int i = 1; i <= len ; i++)
dp[i][1] = qujian[1][i];
for(int i = 1; i <= len ; i++)
{
for(int j = 2; j <= m; j++)
{
for(int k = 1; k < i; k++)
dp[i][j] = max(dp[i][j],dp[k][j-1]*qujian[k+1][i]);
}
}
printf("%lld\n",dp[len][m]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s %d",s,&m);
init();
slove();
}
return 0;
}