一个老生长谈的问题
给出两个整数 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]); } }
原文地址:http://blog.csdn.net/u012349696/article/details/45222301