双线程DP (三维法四维法) sdnu 1032.机器人 1194.传纸条

原题链接:

1032:   http://210.44.14.31/problem/show/1032

1194:   http://210.44.14.31/problem/show/1194


状态转移方程:

三维:

dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - 1][j], dp[k - 1][i][j - 1], dp[k-1][i - 1][j - 1])+jz[i][k+2-i]+jz[j][k+2-j];

四维:

dp[i1][j1][i2][j2] = max(dp[i1 - 1][j1][i2 - 1][j2], dp[i1 - 1][j1][i2][j2 - 1], dp[i1][j1 - 1][i2 - 1][j2], dp[i1][j1 - 1][i2][j2 - 1]) + jz[i1][j1] + jz[i2][j2];


分析见代码。

四维:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int dp[51][51][51][51];
int jz[52][52];
int max(int a, int b, int c, int d)//求四个数中的最大数。(三维法代码上的更快)
{
	int x = a > b ? a : b;
	int y = c > d ? c : d;
	return x > y ? x : y;
}
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n;i++)
	for (int j = 1; j <= m; j++)
		scanf("%d",&jz[i][j]);
	for (int i1 = 1; i1 <= n;i1++)		//i1,j1代表第一个,i2,j2代表第二个。
	for (int j1 = 1; j1 <= m;j1++)
	for (int i2 = 1; i2 <= n;i2++)
	for (int j2 = 1; j2 <= m; j2++)
	{
		dp[i1][j1][i2][j2] = max(dp[i1 - 1][j1][i2 - 1][j2], dp[i1 - 1][j1][i2][j2 - 1], dp[i1][j1 - 1][i2 - 1][j2], dp[i1][j1 - 1][i2][j2 - 1]) + jz[i1][j1] + jz[i2][j2];
		if (i1 == i2&&j1 == j2)			//重叠时减去一个
			dp[i1][j1][i2][j2] -= jz[i1][j1];
	}
	cout << dp[n][m][n][m];//无换行
	return 0;
}

三维:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int dp[105][51][51];
int jz[52][52];
int max(int a, int b, int c, int d)//求四个数中的最大数
{
	if (a >= b&&a >= c&&a >= d) return a;
	else if (b >= c&&b >= d) return b;
	else if (c >= d) return c;
	else return d;
}
int main()
{
	int n, m;
	scanf_s("%d%d", &n, &m);		//注意:虽然输入是 n,m  但矩阵是 m*n。。呵呵~
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++)
		scanf_s("%d", &jz[i][j]);
	int sumbs = m + n - 2;		//算出一共需要走多少步。(自己可以在演草纸上画一下,易得出)
	for (int k = 1; k <= sumbs; k++)		//  注意:k=i+向下走的步数-2		所以下文   k+2-i  k+2-j 分别表示第一个向下走的步数和第二个向下走的步数
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++)
	{
		if (i != j&&k + 2 - i >= 1 && k + 2 - j >= 1)	//1.保证不重叠  2.保证在范围内(k + 2 - i >= 1 && k + 2 - j >= 1也可不写,不写耗时间你懂~)  
			dp[k][i][j] = max(dp[k - 1][i][j], dp[k - 1][i - 1][j], dp[k - 1][i][j - 1], dp[k - 1][i - 1][j - 1]) + jz[i][k + 2 - i] + jz[j][k + 2 - j];
	}
	cout << dp[sumbs][n][n - 1];//易理解:dp[sumbs][n][n - 1]==dp[sumbs][n - 1][n]; 注意:本程序不包含第一个点(即jz[1][1])
	return 0;
}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值