1. 程式人生 > >51Nod 1084 矩陣取數問題 V2(dp降維)

51Nod 1084 矩陣取數問題 V2(dp降維)

一個M*N矩陣中有不同的正整數,經過這個格子,就能獲得相應價值的獎勵,先從左上走到右下,再從右下走到左上。第1遍時只能向下和向右走,第2遍時只能向上和向左走。兩次如果經過同一個格子,則該格子的獎勵只計算一次,求能夠獲得的最大價值。

 

例如:3 * 3的方格。

 

1 3 3

2 1 3

2 2 1

 

能夠獲得的最大價值為:17。1 -> 3 -> 3 -> 3 -> 1 -> 2 -> 2 -> 2 -> 1。其中起點和終點的獎勵只計算1次。

Input

第1行:2個數M N,中間用空格分隔,為矩陣的大小。(2 <= M, N <= 200)
第2 - N + 1行:每行M個數,中間用空格隔開,對應格子中獎勵的價值。(1 <= A[i,j] <= 10000)

Output

輸出能夠獲得的最大價值。

Input示例

3 3
1 3 3
2 1 3
2 2 1

Output示例

17

解釋:https://blog.csdn.net/yuanjunlai141/article/details/51492590

/*
他們兩個走的步數是一致的,並且x+y=步數,可以根據這個進行降維 
*/
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
int dp[403][203][203],a[205][205];
int n,m;
int main()
{
	int i,j,k;
	while(cin>>m>>n)
	{
		for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
		cin>>a[i][j];
		memset(dp,0,sizeof(dp));
		for(k=2;k<=m+n;k++)//最多走m+n步,因為要從左上角走到右下角 
		{
			for(int x1=1;x1<=n && k-x1>=1;x1++) //k代表當前能從起點最多走多少步,所以x1  x2不能超過k-1
			{
				for(int x2=1;x2<=n && k-x2>=1;x2++)
				{
					int d;
					if(x1!=x2)   d=a[x1][k-x1]+a[x2][k-x2];  //數字不能重複取,所以要判斷是否相等 
					else		 d=a[x1][k-x1];
					dp[k][x1][x2]=max(dp[k-1][x1-1][x2] , max(dp[k-1][x1][x2-1] , max(dp[k-1][x1-1][x2-1] , dp[k-1][x1][x2]))) + d; 
				}//max中的4個dp陣列分別代表,(我們把兩個人分別命名為A B)   A從左來,B從上來    A上B左     A左B左     A上B上 
			}
		}
		cout<<dp[m+n][n][n]<<endl;
	}
	return 0;
}