1. 程式人生 > >洛谷P1004方格取數

洛谷P1004方格取數

pre 輸出 得到 class 數字0 tdi 技術 solution 輸出格式

鏈接:https://www.luogu.org/problem/show?pid=1004

題目描述

設有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(表示N*N的方格圖),接下來的每行有三個整數,前兩個

表示位置,第三個數為該位置上所放的數。一行單獨的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
solution:
這題聽說有人跑了個費用流……/斜眼笑
反正我是用dp做的……

記f[i][j][k][l]為第一遍取a[i][j],第二遍取a[k][l]的數時的最大值。
很顯然只能從它們來的地方轉移。
因此f[i][j][k][l]=max(f[i-1][j][k-1][l],f[i-1][j][k][l-1],f[i][j-1][k-1][l],f[i][j-1][k][l-1])+a[i][j]+a[k][l]-a[i][j]*(i==k && j==l);//僅當(i,j)和(k,l)為同一個坐標的時候需要去除重復加的a[i][j](因為a[i][j]只能被取用一次)
然後我們就很愉快地得到了答案。即f[n][n][n][n]。
代碼:
技術分享
 1 #include<iostream>
 2
#include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 int n; 9 int a[20][20]; 10 int dp[20][20][20][20]; 11 int check(int a,int b,int c,int d){ 12 if(a==c && b==d) return 1; 13 else return 0; 14 } 15 int main(){ 16 scanf("%d",&n); 17 int i,j,k,l; 18 int x,y,z; 19 memset(a,0,sizeof(a)); 20 memset(dp,0,sizeof(dp)); 21 while(scanf("%d%d%d",&x,&y,&z)){ 22 if(x==0 && y==0 && z==0){ 23 break ; 24 } 25 a[x][y]=z; 26 } 27 for(i=1;i<=n;++i){ 28 for(j=1;j<=n;++j){ 29 for(k=1;k<=n;++k){ 30 for(l=1;l<=n;++l){ 31 dp[i][j][k][l]=max(max(dp[i-1][j][k][l-1],dp[i-1][j][k-1][l]),max(dp[i][j-1][k][l-1],dp[i][j-1][k-1][l]))+a[i][j]+a[k][l]-a[k][l]*check(i,j,k,l); 32 } 33 } 34 } 35 } 36 printf("%d\n",dp[n][n][n][n]); 37 return 0; 38 }
View Code



洛谷P1004方格取數