乘积最大 | ||||||
| ||||||
Description | ||||||
今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:312, 当N=3,K=1时会有以下两种分法: 1) 3*12=36 2) 31*2=62 这时,符合题目要求的结果是:31*2=62 现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。 | ||||||
Input | ||||||
有多组测试数据。 对于每组测试数据有两行: 第一行共有2个自然数N,K(6≤N≤40,1≤K≤6) 第二行是一个长度为N的数字串。 | ||||||
Output | ||||||
对于每组测试数据,输出一行,为所求得的最大乘积(一个自然数)。 | ||||||
Sample Input | ||||||
4 2 1231 | ||||||
Sample Output | ||||||
62 | ||||||
Source | ||||||
NOIp2000提高组 | ||||||
Recommend | ||||||
黄李龙 |
思路:
1、求最大总价值,考虑dp,设定dp【i】【j】,表示在第i个数后边加了一个乘号,共计已经使用了j个乘号的最大总价值。
2、考虑状态转移方程:
(我们这里用a【i】【j】来表示从i到j的数)
①if(j==1)dp【i】【j】=a【1】【i】;
②dp【i】【j】=max(dp【i】【j】,dp【ll】【j-1】*a【ll+1】【i】);
③if(j==k)dp【i】【j】=dp【i】【j】*a【i+1】【n】;
3、接下来观察到数据范围,N<=40,然而K最小可以达到1,那么显然是需要在dp的基础上套大数的。
那么接下来你需要耐心的去搞高精度,大数乘.....................
耐心.................................
耐心.................................
4、好多daolao都用Java过的..........................
Ac代码:
/*
bignum+Dp
*/
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char dp[45][7][100];
int aa[100];
int bb[100];
int c[10100];
char ans[100];
char a[50];
void mul(char a[],char b[])
{
memset(ans,'\0',sizeof(ans));
memset(aa,0,sizeof(aa));
memset(bb,0,sizeof(bb));
memset(c,0,sizeof(c));
int la=strlen(a);
int lb=strlen(b);
for(int i=0;i<la;i++)
{
aa[la-i-1]=a[i]-'0';
}
for(int j=0;j<lb;j++)
{
bb[lb-j-1]=b[j]-'0';
}
for(int i=0;i<la;i++)
{
for(int j=0;j<lb;j++)
{
c[i+j]+=aa[i]*bb[j];
}
}
int lc=la+lb;
int jinwei=0;
int tmp;
for(int i=0;i<lc;i++)
{
tmp=c[i]+jinwei;
jinwei=tmp/10;
c[i]=tmp%10;
}
int cnt=0;
while(c[lc-1]==0&&lc>1)lc--;
for(int i=lc-1;i>=0;i--)
{
ans[cnt++]=c[i]+'0';
//printf("%d",c[i]);
}
ans[cnt]='\0';
// printf("\n");
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
memset(dp,'\0',sizeof(dp));
scanf("%s",a);
for(int i=0;i<n;i++)
{
for(int j=1;j<=k;j++)
{
if(j==1)
{
//int sum=0;
char sum[100];
int cnt=0;
for(int l=0;l<=i;l++)
{
sum[cnt++]=a[l];
}
sum[cnt]='\0';
strcpy(dp[i][j],sum);
}
for(int ll=0;ll<i;ll++)
{
char sum[100];
int cnt=0;
for(int l=ll+1;l<=i;l++)
{
sum[cnt++]=a[l];
}
sum[cnt]='\0';
mul(dp[ll][j-1],sum);
if(strlen(ans)<strlen(dp[i][j]))continue;
if(strlen(ans)>strlen(dp[i][j]))
{
strcpy(dp[i][j],ans);
}
if(strlen(ans)==strlen(dp[i][j])&&strcmp(dp[i][j],ans)<0)
{
strcpy(dp[i][j],ans);
}
}
if(j==k)
{
char sum[100];
int cnt=0;
for(int l=i+1;l<n;l++)
{
sum[cnt++]=a[l];
}
sum[cnt]='\0';
mul(dp[i][j],sum);
strcpy(dp[i][j],ans);
}
}
}
char output[1000];
memset(output,'\0',sizeof(output));
for(int i=0;i<n-1;i++)
{
if(strlen(output)<strlen(dp[i][k]))
{
strcpy(output,dp[i][k]);
}
if(strlen(output)==strlen(dp[i][k])&&strcmp(dp[i][k],output)>0)
{
strcpy(output,dp[i][k]);
}
}
printf("%s\n",output);
}
}