1. 程式人生 > >hiho 1617 - 方格取數 - dp

hiho 1617 - 方格取數 - dp

包含 ring width ++ 多少 png es2017 alt 不能

題目鏈接

描述

給定一個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; }

hiho 1617 - 方格取數 - dp