1084 矩阵取数问题 V2

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084

一个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

解析:

如果第一条路径先找最优的,就要走路径(1; 1)→(1; 2) → (1; 3) → (2; 3) → (3; 3) → (3; 4) → (3; 5) → (4; 5) → (5; 5)

但是这样(1,5)和(5,3)的两个100就分开了,第二条路径至多取到一个100。

 事实上,我们可以选取这样的两条路径,取得了全部的100:

(1; 1) → (1; 2) → (1; 3) → (1; 4) → (1; 5) → (2; 5) → (3; 5) → (4; 5) → (5; 5)

(1; 1) → (2; 1) → (2; 2) → (2; 3) → (3; 3) → (4; 3) → (5; 3) → (5; 4) → (5; 5)

其实我们可以“两个人一起”dp(让两个人同时走)。
用dp[x1][y1][x2][y2]表示第一个人在(x1,y1) 并且第二个人在(x2,y2)时的最大值。

每个人走一步,状态转移是什么?
dp[x1][y1][x2][y2] = maxfdp[x1'][y1'][x2'][y2']g + a[x1][y1] + a[x2][y2]其中(x1',y1')是(x1,y1)的邻居,(x2',y2')是(x2,y2)的邻居。

事实上,因为我们有这个等式提示我们其实只要用3维就可以表示这个矩阵,                                                                                         因为y2 = x1 + y1 - x2所以那一维可以用走多少步表示出来。
dp[step + 1][x1][x2] = max (dp[step][x1'][x2']g + a[x1][y1] + a[x2][y2])                                                                                                           如果x1 = x2,dp[step + 1][x1][x2]= max(dp[step][x1'][x2']g + a[x1][y1])。

#include<iostream>
#include<cstring>
using namespace std;
int a[210][210];
int dp[500][210][210];
int main()
{
	int m,n;
	cin>>m>>n;
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}//s代表步数,一次最多走一步,要么x加1,要么y加1 
	for(int s=1;s<=m+n;s++){
		for(int x1=1;x1<=n;x1++){
			for(int x2=1;x2<=n;x2++){
				int y1=s-x1;
				int y2=s-x2;
				if(y1>0&&y1<=m&&y2>0&&y2<=m){
					dp[s][x1][x2]=max(max(dp[s-1][x1][x2],dp[s-1][x1-1][x2-1]),
					max(dp[s-1][x1-1][x2],dp[s-1][x1][x2-1]))+
					(x1==x2?a[x1][y1]:a[x1][y1]+a[x2][y2]);//注意加括号 
				}	
			}
		}
	}
	cout<<dp[n+m][n][n]<<endl;	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41555192/article/details/81589388