NYOJ 61 传纸条(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Houheshuai/article/details/51441115


点击打开题目链接

双线dp,dp[sum][x1][x2] 表示两个纸条传递到位置(x1,y1)、(x2,y2)所获得的最大好心程度和

其中 sum = x1 + y1 = x2 + y2,sum记录横纵坐标和

这样就优化到了三维

同单线dp有点相似,只是此处两条路径不能相交,我们在状态转移的时候让 x1 != x2

 
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int maxn  = 50 + 5;
int dp[2 * maxn][maxn][maxn];
int num[maxn][maxn];

int main()
{
	int T, n, m;
	scanf("%d", &T);
	while (T--)
	{
		memset(dp, 0, sizeof(dp));
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				scanf("%d", &num[i][j]);
	
		for (int sum = 3; sum < n + m; sum++)
		{
			for (int x1 = 1; x1 <= n; x1++)		//第一条路的横坐标 
			{
				for (int x2 = x1 + 1; x2 <= n; x2++)	//第两条比第一条的横坐标大 ,不让它们相交 
				{
					if (sum - x1 < 1 || sum - x2 < 1) break;	//由x+y=sum知 y=sum-x 此处控制y的范围,下同 
					if (sum - x1 > m || sum - x2 > m)  continue;
					//状态转移,有四种状态可以转移到当前状态 ,取最大值并加上当前位置的值 
					dp[sum][x1][x2] = num[x1][sum - x1] + num[x2][sum - x2]
						+ max(max(dp[sum - 1][x1][x2], dp[sum - 1][x1 - 1][x2 - 1]),
						  	  max(dp[sum - 1][x1 - 1][x2], dp[sum - 1][x1][x2 - 1]));
				}
			}
		}
		int t = n + m;			//最终结果一定是一个向下走,一个向右走 
		dp[t][n][n] = max(dp[t - 1][n][n - 1], dp[t - 1][n - 1][n]);
		printf("%d\n", dp[t][n][n]);
	}
	return 0;
}        


猜你喜欢

转载自blog.csdn.net/Houheshuai/article/details/51441115
61
今日推荐