/* 整数划分(四)
时间限制:1000 ms | 内存限制:65535 KB
难度:3
描述
暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷。。亲爱的你能帮帮他吗?
问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积
输入
第一行是一个整数T,表示有T组测试数据
接下来T行,每行有两个正整数 n,m ( 1<= n < 10^19, 0 < m <= n的位数);
输出
输出每组测试样例结果为一个整数占一行
样例输入
2
111 2
1111 2
样例输出
11
121
来源
经典题目
*/
//思路:区间dp,设dp[i][j] 表示在区间[0, i]之中,插入j个乘号可以得到的最大数
//设a[i][j]为区间[i,j]所形成的数所以 dp[i][j] = max(dp[k][j-1] * a[k + 1][i])
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
ll dp[25][25];
ll a[25][25];
char b[25];
ll fun(int i, int j){ //注意递归的条件
if(dp[i][j] != 0)
return dp[i][j];
if(i < j) //可以等于
return 0;
if(i == 0 || j == 0){
return dp[i][j] = a[0][i];
}
for(int k = 0; k <= i - 1; k++){
dp[i][j] = max(fun(k, j - 1)*a[k+1][i], dp[i][j]);
// cout << "k : " << k << " " << "i :" << i << " a: " << a[k+1][i] << " " << dp[i][j] << endl;
}
return dp[i][j];
}
int main(){
int n;
cin >> n;
while(n--){
memset(dp, 0, sizeof(dp));
memset(b, 0, sizeof(b));
memset(a, 0, sizeof(a));
ll s = 0, m = 0;
// while(~scanf("%c", &b[s++]))
// ;
scanf("%s", b);
scanf("%lld", &m);
s = strlen(b);
if(m > s){
cout << 0 << endl;
continue;
}
for(int i = 0; i < s; i++){
a[i][i] = b[i] - '0';
for(int j = i + 1; j < s; j++){
a[i][j] = a[i][j - 1] * 10 + b[j] - '0';
}
}
//递归:
// printf("%lld\n", fun(s - 1, m - 1));
//递推:
for(int i = 0; i < s; i++)
dp[i][0] = a[0][i];
for(int i = 1; i < s; i++){
for(int j = 1; j <= m - 1; j++){
for(int k = 0; k < i; k++)
dp[i][j] = max(dp[i][j], dp[k][j - 1]*a[k+1][i]);
}
}
cout << dp[s-1][m-1] << endl;
/*
for(int i = 0; i < s; i++){
for(int j = 0; j < s; j++)
cout << a[i][j] << " ";
cout << endl;
}
*/
}
return 0;
}