原题链接
题目大意
有一个长的为 n ( 6 ≤ n ≤ 40 ) n(6\le n\le 40) n(6≤n≤40)的字符串,你要在其中任意添加 k ( 1 ≤ k ≤ 6 ) k(1\le k\le 6) k(1≤k≤6)个乘号,求得到的最大值是多少。
结题思路
如果使用暴力枚举,时间复杂度就会为:
O
(
4
n
)
O(4^n)
O(4n),超时。这时候,我们考虑动态规划。假如我们设
f
(
n
,
k
)
f_{(n,k)}
f(n,k)表示前
n
n
n个位置放
k
k
k个乘号的最大结果,设
r
(
i
,
j
)
r_{(i,j)}
r(i,j)表示字符串中第
i
∼
j
i\sim j
i∼j位的数字,则:
f
(
i
,
j
)
=
{
j
=
0
r
(
i
,
j
)
max
i
≤
k
<
j
(
f
(
k
,
i
)
,
f
(
k
,
i
)
×
r
(
k
,
j
)
)
f_{(i,j)}=\left\{\begin{matrix}j=0\ \ \ \ \ r_{(i,j)} \\ \max_{i\le k<j} (f_{(k,i)},f_{(k,i)}\times r_{(k,j)}) \end{matrix}\right.
f(i,j)={j=0 r(i,j)maxi≤k<j(f(k,i),f(k,i)×r(k,j))
就为状态转移方程,最终的答案就被存储在
f
(
n
,
k
)
f_{(n,k)}
f(n,k)中。
代码实现
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
string s,r[100][100],f[100][100];
int n,k;
string cheng(string s1,string s2)//字符串高精乘法
{
if(s1=="0"||s2=="0") return "0";//任何数乘0等于0
string s3="",s4="",ans="",re="";
long long len1=0,len2=0,jw=0,t=0,ansi=0;
len1=s1.size();
len2=s2.size();
for(long long i=1;i<=len2+1;i++) s1='0'+s1;//补前缀0
for(long long i=len1+len2;i>=0;i--) s3+=s1[i],ans+="00";//防止RE
for(long long i=1;i<=len1+1;i++) s2='0'+s2;//补前缀0
for(long long i=len1+len2;i>=0;i--) s4+=s2[i];
long long s3x=0,s4x=0;
while(s3[s3x]=='0') s3x++;
while(s4[s4x]=='0') s4x++;
s3=s3.substr(s3x,s3.size()-s3x);
s4=s4.substr(s4x,s4.size()-s4x);
for(long long i=0;i<s3.size();i++)
for(long long j=0;j<s4.size();j++){
t=int(s3[i]-'0')*int(s4[j]-'0')+jw;
ansi=(t+(ans[i+j]-'0'));//转数字进行计算
jw=ansi/10;
ans[i+j]=char(ansi%10+'0');//转回字符存储
}
for(long long i=1;i<=s3x+s4x;i++) ans="0"+ans;
long long b=ans.size()-1;
while(b>=1&&ans[b]=='0') b--;//去前缀0
for(long long i=b;i>=0;i--) re+=ans[i];//倒序遍历
return re;
}
bool q_bigger_h_setup(string q,string h)
{
if(q.size()!=h.size()) return q.size()>h.size();//比较大小
else return q>h;//比较大小
}
string _max(string a,string b){//返回较大字符串
if(q_bigger_h_setup(a,b))
return a;
return b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
cin>>s;
for(int i=0;i<n;i++)
for(int j=i;j<n;j++)
r[i][j]=s.substr(i,j-i+1);
for(int i=1;i<=k;i++)
for(int j=1;j<=n;j++)
f[i][j]="0";
for(int i=1;i<=n;i++)//初始化
f[i][0]=r[0][i-1];
for(int k2=1;k2<=k;k2++)//动态规划
for(int i=k2+1;i<=n-k+k2;i++)
for(int j=k2;j<i;j++)
f[i][k2]=_max(f[i][k2],cheng(f[j][k2-1],r[j][i-1]));
cout<<f[n][k];
return 0;
}
样例
输入
4 2
1231
输出
62