1. 程式人生 > 其它 >題解:方格取數

題解:方格取數

目錄

題目

設有 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;
}