当前位置: 首页 > news >正文

算法题(206):方格取数(动态规划)

审题:
本题需要我们找到两条从起点到终点的路径,使得这两条路径取得的路径和最大,走过的路的数就被取走了,无法再次获得

思路:

方法一:贪心+动态规划

贪心方案:直接走两次该矩阵,每次走都按照寻找最大路径和的方法走

该方案存在问题,因为可以举出反例

图示:

这是按照贪心方案走的两条路线,我们发现这样会漏掉一个左下角的1

接下来我们看看最优解路线

最优解情况可以把左下角的1也取到


方法二:动态规划

(1)状态表示:f[s][i1][i2]表示横纵坐标之和为s的时候走到(i1,j1)与(i2,j2)点的最大路径和

由于分开走是行不通的,所以我们这次尝试同时走,就是有两条路径(路径1与路径2),且由于他们是同时从同一个起点出发的所以他们的初始横纵坐标和与走的步数都是相同的(走一步则横纵坐标和++)

故:i1 + j1 = i2 + j2 = s

那么我们其实可以将状态表示为f[i1][j1][i2][j2],不过这是四维的,且有很多非法坐标需要排除,所以我们尝试将状态表示降维

根据上面的等式,我们知道j1和j2其实可以根据i1和i2求出来

即:j1 = s - i1      j2 = s - i2

也就是说只要确定了s,i1,i2那么两个坐标的位置其实也确定了,三维的状态表示最终就可以表示为f[s][i1][i2]

(2)状态转移方程:

由于这次有两个路径所以我们分析的时候也要依次分析

根据最后一步分析法,当前路径和一定是由走了s-1步的路径和+当前位置的值得来的,所以我们可以确定第一个参数一定是s-1

然后我们根据行走规则进行后面的判断,总共分四种走法(左侧表示i1,右侧表示i2)

注意:这里的方位表示要走的路径相对于目标位置的方位

1.左+左   :

由于都是在(i,j)的左侧向右侧移动一步,移动节点和目标节点处于同一行,所以第二和第三个参数分别直接等于i1,i2 

即:f[s-1][i1][i2]

2.左+上   

这里移动到(i1,j1)的节点在其左侧,故第二个参数仍为i1.然后移动到(i2,j2)的节点在其上方一行,故第三个参数为i2-1

3.上+左 

4.上+上

3和4与上面同理分析即可

在将前面的最大路径和确定好之后,我们只需要再加上(i1,j1)与(i2,j2)的值就行。

注意:有可能i1 == i2,也就是这两个目标节点是同一个节点,此时由于值只能取得一次,所以我们要特殊判断,特殊处理

(3)初始化:
f数组初始化为0即可,因为数据值都是大于0的,所以0不会影响取值

(4)填表顺序:从上到下,从左到右

还是依据行走规则来制定填表顺序

(5)答案输出:f[2*n][n][n]

解题:
 

#include<iostream>
using namespace std;
const int N = 15;
int a[N][N], f[2 * N][N][N];//f[s][i1][i2]表示横纵坐标之和为s的时候走到(i1,j1)与(i2,j2)的最大路径和
int n,x,y,v;
int main()
{//数据录入cin >> n;while ((cin >> x >> y >> v, x && y && v)){a[x][y] = v;}//填表for (int s = 2; s <= 2 * n; s++)//sfor(int i1 = 1; i1 <= n; i1++)for (int i2 = 1; i2 <= n; i2++){int j1 = s - i1; int j2 = s - i2;if (j1 > n || j2 > n) continue;//非法访问int t1 = max(f[s - 1][i1][i2], f[s - 1][i1][i2 - 1]);int t2 = max(f[s - 1][i1 - 1][i2], f[s - 1][i1 - 1][i2 - 1]);if (i1 == i2){f[s][i1][i2] = max(t1, t2) + a[i1][j1];}else{f[s][i1][i2] = max(t1, t2) + a[i1][j1] + a[i2][j2];}}//输出答案cout << f[2 * n][n][n] << endl;return 0;
}

1.录入数据需要注意,题目中说了节点值的录入当且仅当三个值都不为0的时候结束录入。

所以我们利用逗号表达式,实现录入数据的同时判断是否满足结束条件,满足就直接退出循环

2.s的范围是从2到2n,因为根据题目用例,我们发现左上角的起点是(1,1),所以起始的横纵坐标和就是2,结束的位置是(n,n)所以s的最大值就是2n

P1004 [NOIP 2000 提高组] 方格取数 - 洛谷


文章转载自:

http://4RFSkAD7.mfcbk.cn
http://nWJi05VS.mfcbk.cn
http://ZKo2T3jA.mfcbk.cn
http://XIKIq653.mfcbk.cn
http://RXKcqZfz.mfcbk.cn
http://4BbgxFVS.mfcbk.cn
http://aNJouZEV.mfcbk.cn
http://my8vtH5t.mfcbk.cn
http://quBrpIpS.mfcbk.cn
http://kVJxqErV.mfcbk.cn
http://OIcpE94v.mfcbk.cn
http://AmUlyxwu.mfcbk.cn
http://G8KmAM6W.mfcbk.cn
http://EB4d4daN.mfcbk.cn
http://5IX3VQTx.mfcbk.cn
http://6sVjzkxm.mfcbk.cn
http://uEJABAqy.mfcbk.cn
http://GIFYyeFV.mfcbk.cn
http://tlPtilT6.mfcbk.cn
http://gQMlz0mP.mfcbk.cn
http://CDN0Kqvf.mfcbk.cn
http://kN1Zxc52.mfcbk.cn
http://YKqsnU70.mfcbk.cn
http://OMpbas3j.mfcbk.cn
http://1l2cq0zQ.mfcbk.cn
http://WJgtX0Up.mfcbk.cn
http://HBy2dL5X.mfcbk.cn
http://6Nyvd0XB.mfcbk.cn
http://Fa8oafKL.mfcbk.cn
http://MsWP8JBQ.mfcbk.cn
http://www.dtcms.com/a/382605.html

相关文章:

  • 第十六周周报
  • [硬件电路-193]:双极型晶体管BJT与场效应晶体管FET异同
  • ID3v2的header中的扩展标头(Extended Header),其Size字段如何计算整个ID3的长度?
  • 【51单片机】【protues仿真】基于51单片机的篮球计时计分器系统
  • Linux -- 权限的理解
  • Java零基础学习Day10——面向对象高级1
  • 解析通过base64 传过来的图片
  • Redis 持久化策略
  • STM32---PWR
  • 0913刷题日记
  • Java基础面试篇(7)
  • 4-机器学习与大模型开发数学教程-第0章 预备知识-0-4 复数与指数形式(欧拉公式)
  • TA-VLA——将关节力矩反馈融入VLA中:无需外部力传感器,即可完成汽车充电器插入(且可多次自主尝试)
  • 从0到1开发一个商用 Agent(智能体),Agent零基础入门到精通!_零基础开发aiagent 用dify从0到1做智能体
  • android 消息队列MessageQueue源码阅读
  • Gtest2025大会学习记录(全球软件测试技术峰会)
  • oneshape acad数据集 sam-dataset
  • 堆(优先队列)
  • 【卷积神经网络详解与实例】7——经典CNN之AlexNet
  • Digital Clock 4,一款免费的个性化桌面数字时钟
  • mysql 必须在逗号分隔字符串和JSON字段之间二选一,怎么选
  • 分布式锁介绍与实现
  • 海盗王客户端dx9的64位release版测试
  • MX模拟赛总结
  • FLEXSPI_Init 硬件故障问题
  • Linux进程概念(下):进程地址空间
  • C++11_3(智能指针篇)
  • 从理论到实践:构建高效AI智能体系统的架构演进
  • 如何运用好DeepSeek为自己服务:智能增强的范式革命 | 1.3 人机认知耦合协议
  • 什么是PV操作?