题目链接
看完题可能第一时间并没有清晰的思路。让我们一步一步的来考虑这道题目。
题目中描述操作为每次从所有的行中选取,这样做有些麻烦。仔细思考一下可以发现行与行之间互不干涉,所以我们可以对每行操作到底,最后统计答案。
每行怎么选取当然难不倒聪明的oier了,设f[i][j]表示某行从第i位到第j位的最优答案。
转移如下
f[i][j]=max((f[i+1][j]+b[i]<<1),(f[i][j-1]+b[j]<<1));
到此,这道题目就做完了。
1 #include<cstring> 2 #include<iostream> 3 #include<cctype> 4 #include<cstdio> 5 #include<algorithm> 6 #define ll __int128_t 7 using namespace std; 8 inline ll read() 9 { 10 register ll X=0;register char ch=0; 11 for(;!isdigit(ch);ch=getchar()); 12 for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+(ll)ch-'0'; 13 return X; 14 } 15 inline void write(ll x) 16 { 17 if(x>9) write(x/10); 18 putchar(x%10+'0'); 19 } 20 int n,m; 21 ll a[81][81],f[81][81],ans; 22 ll work(ll b[]) 23 { 24 memset(f,0,sizeof(f)); 25 for(int l=0;l<=m;l++) 26 for(int i=1;i+l<=m;i++) 27 { 28 int j=i+l; 29 f[i][j]=max((f[i+1][j]+b[i]<<1),(f[i][j-1]+b[j]<<1)); 30 } 31 return f[1][m]; 32 } 33 int main() 34 { 35 n=read(),m=read(); 36 for(int i=1;i<=n;i++) 37 for(int j=1;j<=m;j++) 38 a[i][j]=read(); 39 for(int i=1;i<=n;i++) 40 ans+=work(a[i]); 41 write(ans); 42 }
需要注意的是,这道题目由于数据范围过大需要使用高精度运算,然而在洛谷上是可以用_int128水过去的。