思路:典型dp,第一部分的for双重循环语句把一个大数字拆分成小数字的所有形式,第二部分就是比较了,从0开始遍历,dp[i] 是指第i项以及前面的项中最大的和。
数组a[i][j]用于表示以i为首以j为尾的值
这里状态转移方程在逐步将i的元素进行求和,dp[j]用于表示前j项最大值,a[j+1][i]就是表示后面整体的值
这里j相当于一个分割点,将一段数字分成两半
我们先假设没有关键点1,,看看关键点2(代码标注),这个循环用于求dp[i],但是我们发现这样不能枚举出a[0][i]的情况,于是我就加入了关键点1实现枚举a[0][i]。
#include<stdio.h>
#include<string.h>
#define limit 2147483647
#define max(a,b) a>b?a:b
long long a[1000][1000],dp[1000];
int main()
{
long long j,k,i,g,h,y,x,n,m,r,t,q,u;
char b[300];
scanf("%lld",&u);getchar();
for(q=1;q<=u;q++)
{
memset(b,'\0',sizeof(b));
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
scanf("%s",b);
long long len=strlen(b);
for(i=0;i<=len-1;i++)
{
long long num=0;
for(j=i;j<=len-1;j++)
{
num=num*10+(b[j]-'0');
if(num>limit) break;
a[i][j]=num;
}
}
for(i=0;i<=len-1;i++)//dp[i]表示坐标i及之前和的最大值
{
dp[i]=a[0][i];//关键点1
for(j=0;j<=i;j++)//关键点2
{
dp[i]=max(dp[i],dp[j]+a[j+1][i]);
}
}
printf("%lld\n",dp[len-1]);
}
return 0;
}