整数划分(四)
时间限制:
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
-
第一行是一个整数T,表示有T组测试数据
数据比较小,想着搜索先来一发,居然0ms,数据有点水
搜索:枚举每一种组合,刷新m段时的最小值
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=20;
ll sum[N][N];
char s[N];
ll n,maxx,m;
void dfs(ll r,ll ans,ll step)
{
if(step==m)
{
maxx=max(maxx,ans);
return;
}
for(ll i=1;i<=n-m+1;i++)
{
if(r+i<=n)
{
dfs(r+i,ans*sum[r+1][r+i],step+1);
}
}
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
mem(sum,0);
maxx=0;
scanf("%s %lld",s+1,&m);
n=strlen(s+1);
for(ll i=1; i<=n; i++)
{
sum[i][i]=s[i]-'0';
for(ll j=i+1; j<=n; j++)
{
sum[i][j]=sum[i][j-1]*10+s[j]-'0';
}
}
dfs(0,1,0);
printf("%lld\n",maxx);
}
}
区间DP:
dp[i][j]表示1~i被分成j段的最大值
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=20;
ll sum[N][N],dp[N][N];
char s[N];
ll n,maxx,m;
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
mem(sum,0);
mem(dp,0);
scanf("%s %lld",s,&m);
n=strlen(s);
for(ll i=0; i<n; i++)
{
sum[i][i]=s[i]-'0';
for(ll j=i+1; j<n; j++)
{
sum[i][j]=sum[i][j-1]*10+s[j]-'0';
}
}
for(ll i=0;i<n;i++)
{
dp[i][1]=sum[0][i];
for(ll j=2;j<=m;j++)
{
for(ll k=j-2;k<i;k++)
{
dp[i][j]=max(dp[i][j],dp[k][j-1]*sum[k+1][i]);
}
}
}
printf("%lld\n",dp[n-1][m]);
}
}