一个老生长谈的问题
给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积
区间dp:
思路:先求出n从 i~j数位的 值
分析 m段的情况
4位的数 定义dp【i】【j】为讲 i 分为 j 段 的最大乘积值 为了更加直观 我颠倒了一下i j 让大家看得明白些
0 1 2 3 // i
j 0 1 11 111 1111
1 0 1 11 121
2 0 0 0 0
3 0 0 0 0
#include<bits/stdc++.h>
using namespace std;
long long dp[50][50];
long long a[50][50];
char n[50];
int m;
void add(int x,int y)
{
int k = 1;
for(int i = y;i>=x;i--)
{
a[x][y]+=((n[i]-'0')*k);
k*=10;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%d",n,&m);
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(dp));
int L = strlen(n);
for(int i = 0;i <L ;i++)
{
for(int j = i;j < L;j++)
{
add(i,j);//计算每个区间内的【i,j】
}
}
for(int i=0;i<L;i++)
dp[i][0] = a[0][i];//dp【i】【j】为把 i 这个数分为j 份 的最大乘积 千万注意 dp【i】【j】与 a【i】【j】 是颠倒的
m--;
for(int j = 1; j <= m;j++)
{
for(int i = j;i <L;i++)
{
for(int k = 0; k < i;k++)
{
dp[i][j] = max(dp[i][j],dp[k][j-1]*a[k+1][i]);//dp[1,2] = dp[0,1]*dp[1][2]
}
}
}
for(int i = 0;i<L;i++)
{
for(int j = 0;j<L;j++)
{
printf("%d ",dp[j][i]);
}
printf("\n");
}
printf("%lld\n",dp[L-1][m]);
}
}