思路:
首先当然是每行单独处理 再把答案相加
我们发现如果知道还没有取数的区间长度 就知道现在取了多少个数
也就是说我们可以知道现在要取的数做贡献要乘的系数
每次取数只能在左右两端取 所以转移的时候在这两种情况中取min即可
记搜会很方便啊
CODE:
View Code1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int read() 6 { 7 int x=0,y=1;;char ch; 8 ch=getchar(); 9 while(ch<'0'||ch>'9') {if(ch=='-') y=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 11 return x*y; 12 } 13 __int128 n,m,a[100],ans; 14 __int128 f[100][100],p[100]; 15 __int128 dfs(int l,int r) //从l到r的区间 16 { 17 if(f[l][r]!=-1) return f[l][r]; 18 if(l==r) return p[m]*a[l]; 19 f[l][r]=max(a[l]*p[(m-r+l)]+dfs(l+1,r),a[r]*p[m-r+l]+dfs(l,r-1)); 20 return f[l][r]; 21 } 22 void print(__int128 x) 23 { 24 if(!x) return; 25 if(x) print(x/10); 26 putchar(x%10+'0'); 27 } 28 int main() 29 { 30 n=read();m=read(); 31 p[1]=2; 32 for(int i=2;i<=m;i++) p[i]=p[i-1]<<1; 33 for(int i=1;i<=n;i++) 34 { 35 memset(f,-1,sizeof(f)); 36 for(int j=1;j<=m;j++) a[j]=read(); 37 ans+=dfs(1,m); 38 } 39 if(ans==0) cout<<"0"; 40 print(ans); 41 return 0; 42 }