题目描述
设有 n \times mn×m 的方格图,每个方格中都有一个整数。现有一只小熊,想从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。小熊会取走所有经过的方格中的整数,求它能取到的整数之和的最大值。
输入格式
第一行有两个整数 n, mn,m。
接下来 nn 行每行 mm 个整数,依次代表每个方格中的整数。
输出格式
一个整数,表示小熊能取到的整数之和的最大值。
样例 #1
样例输入 #1
3 4
1 -1 3 2
2 -1 4 -1
-2 2 -3 -1
Copy
样例输出 #1
9
Copy
样例 #2
样例输入 #2
2 5
-1 -1 -3 -2 -7
-2 -1 -4 -1 -2
Copy
样例输出 #2
-10
Copy
提示
样例 1 解释
样例 2 解释
数据规模与约定
- 对于 20\%20% 的数据,n, m \le 5n,m≤5。
- 对于 40\%40% 的数据,n, m \le 50n,m≤50。
- 对于 70\%70% 的数据,n, m \le 300n,m≤300。
- 对于 100\%100% 的数据,1 \le n,m \le 10^31≤n,m≤103。方格中整数的绝对值不超过 10^4104。
思路
首先,可以先定义一个三位数组at[i][j][k],i,j为位置,k为上一步方向。
这样就可以得出公式:
j>1:
i>1:
i<n:
代码见下:
#include<bits/stdc++.h>
using namespace std;
long long iom[1024][1024],n,m,x,a,aa[2024][2024],at[2001][2001][5],dd0=-10,aaa=-1e17+1;
long long maxx(long long a,long long b){
// return a>b;
if(a<=b) return b;
else return a;
}
int main(){
cin>>n>>m;
memset(at,-63,sizeof(at));
for(long long i=1;i<=n;i++){
for(long long j=1;j<=m;j++){
cin>>aa[i][j];
at[i][j][0]=aaa;
at[i][j][1]=aaa;
at[i][j][2]=aaa;
}
}
at[1][1][0]=aa[1][1];
at[1][1][1]=aa[1][1];
at[1][1][2]=aa[1][1];
for(long long i=2;i<=n;i++){
at[i][1][1]=at[i-1][1][1]+aa[i][1];
}
for(long long j=1;j<=m;j++){
for(long long i=1;i<=n;i++){
if(j!=1) at[i][j][0]=maxx(at[i][j-1][1],maxx(at[i][j-1][0],at[i][j-1][2]))+aa[i][j];
if(i>=2){
at[i][j][1]=maxx(at[i-1][j][0],at[i-1][j][1])+aa[i][j];
}
}
for(long long i=n-1;i>=1;i--){
at[i][j][2]=maxx(at[i+1][j][0],at[i+1][j][2])+aa[i][j];
}
}
cout<<maxx(at[n][m][1],maxx(at[n][m][0],at[n][m][2]));
}