描述
给定一个NxN的方格矩阵,每个格子中都有一个整数Aij。小Hi和小Ho各自选择一条从左上角格子到右下角格子的路径,要求路径中每一步只能向右或向下移动,并且两条路径不能相交(除了左上右下起止方格)。
现在将两条路径经过的整数加起来求和。你能计算出这个和最大是多少吗?
输入
第一行包含一个整数N。
以下N行每行包含N个整数,代表方格矩阵中的数字。
对于50%的数据,1 ≤ N ≤ 50
对于100%的数据,1 ≤ N ≤ 200 1 ≤ Aij ≤ 100
---------------------------------------------------------------------------------------------------------------------------------------------
如下图那样一行行的处理
dp[row][i][j]代表 第row行选取第i和第j个元素时的最大值,
dp[row][i][j]最多只和上一行的四个元素相关,注意上三角和下三角这四个元素的索引方式不同。
因为第row行只和第row-1行相关,所以只需保存前一行的结果。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 256; int dp[N][N][2]; int A[N][N]; int n; int get(int row,int i){ if(row<=n+1){ if(i>=row) return 0; return A[row-i][i]; } else{ int x = row-n-1+i; if(x>n) return 0; return A[row-x][x]; } } int main(){ cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&A[i][j]); memset(dp,0,sizeof(dp)); dp[1][1][0] = A[1][1]*2; int cur = 1; for(int row=3;row<n*2;row++){ int cnt = (row>n+1)?(n*2-row+1+1):(row); int gap = (row>n+1)? 1: -1; for(int i=1;i<cnt;i++) for(int j=i+1;j<cnt;j++){ int max1 = std::max(dp[i][j][!cur],dp[i+gap][j][!cur]); int max2 = std::max(dp[i][j+gap][!cur],dp[i+gap][j+gap][!cur]); dp[i][j][cur] = std::max(max1,max2)+get(row,i)+get(row,j); } cur = cur?0:1; } printf("%d\n",dp[1][2][!cur]+A[n][n]*2); return 0; }