2021.3.15学习随笔_dp问题_数字三角形_两条线路之和最大

学习随笔

方格取数

  • 动态规划问题
    • 数字三角形
      题目具体链接
      题目描述:找到一个矩阵中,两条线路之和最大的情况,并且把最大值输出
#include <iostream>
#include<algorithm>
using namespace std;
const int N = 15;
int n;
int w[N][N], f[N * 2][N][N];//三维来记录两个人的位置,两个人同时走
//两个小朋友同时走k步,从(1,1),(1,1)走到(i1,j1),(i2,j2)能获得的最大花生数目.
int main() {
	cin >> n;
	int a, b, c;
	while (cin >> a >> b >> c)
	{
		w[a][b] = c;
		if (a || b || c) break;
	}
	for (int k = 2; k <= 2 * n; k++) 
	{
		for (int i1 = 1; i1 <= n; i1++) 
		{
			for (int i2 = 1; i2 <= n; i2++) 
			{
				int j1 = k - i1, j2 = k - i2;
				if (j1 >= 1 && j1 <= n&&j2 >= 1 && j2 <= n) 
				{
					// 不能越界
					int &x = f[k][i1][i2];//声明x是f[k][i1][i2]的别名
					int t = w[i1][j1];//单个权重
					if (i1 != i2) t += w[i2][j2];//位置不同
					//不重合则需要加两个权重.
					x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);//都向下走
					x = max(x, f[k - 1][i1 - 1][i2] + t);//一个向下,一个向右
					x = max(x, f[k - 1][i1][i2 - 1] + t);//一个向右一个向下
					x = max(x, f[k - 1][i1][i2] + t);//都向右
					//保留最大属性
				}
			}
		}
	}
	cout << f[n * 2][n][n] << endl;
	return 0;
}

学习产出:

1、 用的是f[N*2][N] 用前面的来记录步数,后面的记录其中一条路线当前所在的位置,当同时走的时候,就可以用来记录多条路线之和
2、int &x = f[k][i1][i2]; 当要输出的值很长时,用&别称可以,简化输出。
3、f[k][i1][i2];代表的是两个位置(i1,k-i1)和(i2,k-i2),有两个点,达到这个位置,并且要保证两个点一起走,可以1号点向下,2号点向下或者1号点向下,2号点向右,简化向下为0 向右为1 则是00 01 10 11四种情况。代表的含义是,f[k][i1][i2]取这四种情况的最大值
递推式:
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);//都向下走
x = max(x, f[k - 1][i1 - 1][i2] + t);//一个向下,一个向右
x = max(x, f[k - 1][i1][i2 - 1] + t);//一个向右一个向下
x = max(x, f[k - 1][i1][i2] + t);//都向右

以此思想推广
用f[N*2][N] [N][N]就可以记录在二维数组中的三条线路,并且递推公式可以的出是(简化向下为0 向右为1)000、001、010、011、100、101、110、111 八种情况的最大值。

发现: 根据观察发现,由于在同一个点不能取两次值,则根据题目要求取最大值的特性,多条线路不可能重合,因为这会导致重合点重复。也就是说正确的解,两条线路一定是一上一下的。
具体解释感谢vlehr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值