題解:方格取數
阿新 • • 發佈:2021-06-19
目錄
題目
設有 N×N 的方格圖 (N≤9),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。如下圖所示(見樣例):
A
0 0 0 0 0 0 0 0
0 0 13 0 0 6 0 0
0 0 0 0 7 0 0 0
0 0 0 14 0 0 0 0
0 21 0 0 0 4 0 0
0 0 15 0 0 0 0 0
0 14 0 0 0 0 0 0
0 0 0 0 0 0 0 0
B
某人從圖的左上角的A點出發,可以向下行走,也可以向右走,直到到達右下角的B點。在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字0)。
此人從A點到B點共走兩次,試找出2條這樣的路徑,使得取得的數之和為最大。
輸入格式
輸入的第一行為一個整數N(表示 NxN 的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。
輸出格式
只需輸出一個整數,表示2條路徑上取得的最大的和。
輸入輸出樣例
輸入
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
輸出
67
解析
我們定義dp[i][j][k][h] 表示兩條路徑,走到a[i][j]和a[k][h]時的最大值,所以我們可以寫一個四重迴圈,內部含有四個判斷,表示兩個點從上,下,左,右繼承而來,加上在連個點的最大值。
特別注意:如果兩個點重合的話需要減掉一個點的值,不然結果會偏大。。。調了好久才發現這個問題
程式碼
#include<bits/stdc++.h> #define int long long #define max(a,b,c,d) max(max(a,b),max(c,d)) using namespace std; int n; int a[1001][1001] = { }; int dp[50][50][50][50]; signed main(){ scanf("%lld" ,&n); while(1) { int x,y,c; scanf("%lld %lld %lld" ,&x,&y,&c); if(x == 0 && y == 0 && c == 0) break; a[x][y] = c; } for(int i = 1;i <= n; i++) { for(int j = 1;j <= n; j++) { for(int k = 1;k <= n; k++) { for(int h = 1;h <= n; h++) { dp[i][j][k][h] = max(dp[i - 1][j][k - 1][h] + a[i][j] + a[k][h],dp[i - 1][j][k][h - 1] + a[i][j] + a[k][h],dp[i][j - 1][k - 1][h] + a[i][j] + a[k][h],dp[i][j - 1][k][h - 1] + a[i][j] + a[k][h]); if(i == k && j == h) dp[i][j][k][h] -= a[i][j]; } } } } printf("%lld" ,dp[n][n][n][n]); return 0; }