传送门
解题思路
每行互不影响,所以分开处理,对于每一行,很显然是个区间dp,我们用dp[i][j]表示区间[i..j]的得分和的最大值,注意每次加一个数的顺序是先加上数再集体乘2。
恶心的地方在于需要写高精(学校比赛懒得写,所以只拿了60分),需要一个高精度+int,一个高精度*2,一个高精度+高精度三个函数,同时因为dp要取max,所以需要重定义struct里的<。
AC代码
1 //dp[i][j]表示区间[i..j]的最大值 dp[i][j]=max(dp[i+1][j]+a[i]*k,dp[i][j-1]+a[j]*k) 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 using namespace std; 7 long long n,m,a[85]; 8 struct node{ 9 int shu[55]; 10 bool operator <(const node b) const { 11 if(shu[0]!=b.shu[0]) return shu[0]<b.shu[0]; 12 for(int i=shu[0];i>=1;i--){ 13 if(shu[i]!=b.shu[i]) return shu[i]<b.shu[i]; 14 } 15 return 1; 16 } 17 }dp[85][85],anss; 18 node add(node a,int x){ 19 a.shu[1]+=x; 20 int cnt=1; 21 while(cnt<a.shu[0]||a.shu[cnt]>=10){ 22 a.shu[cnt+1]+=a.shu[cnt]/10; 23 a.shu[cnt]%=10; 24 cnt++; 25 } 26 a.shu[0]=max(a.shu[0],cnt); 27 return a; 28 } 29 node cheng(node a,int x){ 30 int cnt=a.shu[0]; 31 for(int i=1;i<=cnt;i++){ 32 a.shu[i]*=x; 33 } 34 cnt=1; 35 while(cnt<a.shu[0]||a.shu[cnt]>=10){ 36 a.shu[cnt+1]+=a.shu[cnt]/10; 37 a.shu[cnt]%=10; 38 cnt++; 39 } 40 a.shu[0]=max(a.shu[0],cnt); 41 return a; 42 } 43 node add2(node a,node b){ 44 int cntt=max(a.shu[0],b.shu[0]); 45 for(int i=1;i<=cntt;i++) a.shu[i]+=b.shu[i]; 46 int cnt=1; 47 while(cnt<cntt||a.shu[cnt]>=10){ 48 a.shu[cnt+1]+=a.shu[cnt]/10; 49 a.shu[cnt]%=10; 50 cnt++; 51 } 52 a.shu[0]=max(a.shu[0],cnt); 53 return a; 54 } 55 int main(){ 56 cin>>n>>m; 57 for(int hang=1;hang<=n;hang++){ 58 memset(dp,0,sizeof(dp)); 59 for(int i=1;i<=m;i++) cin>>a[i]; 60 for(int i=1;i<=m;i++) dp[i][i]=add(dp[i][i],2*a[i]); 61 for(int k=1;k<m;k++){ 62 for(int i=1;i<=m-k;i++){ 63 int j=i+k; 64 dp[i][j]=cheng(max(add(dp[i+1][j],a[i]),add(dp[i][j-1],a[j])),2); 65 } 66 } 67 anss=add2(anss,dp[1][m]); 68 } 69 for(int i=anss.shu[0];i>=1;i--){ 70 cout<<anss.shu[i]; 71 } 72 return 0; 73 }