详解平面DP(上)

前言

其实平面DP和正常的dp没有什么本质上的区别,只不过是在二维的面上进行DP,而且,客观的说,其实和递推没有什么区别,不要把他想的太难了

讲解

本蒻鸡思前想后,好像关于平面DP的理论知识好像没有什么,所以我们直接上题,从题来入手

[NOIP2000 提高组] 方格取数

题目传送门

题目背景

NOIP 2000 提高组 T4

题目描述

设有 N × N N \times N N×N 的方格图 ( N ≤ 9 ) (N \le 9) (N9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0 0 0。如下图所示(见样例):

某人从图的左上角的 A A A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B B B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0 0 0)。
此人从 A A A 点到 B B B 点共走两次,试找出 2 2 2 条这样的路径,使得取得的数之和为最大。

输入格式

输入的第一行为一个整数 N N N(表示 N × N N \times N N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 0 0 表示输入结束。

输出格式

只需输出一个整数,表示 2 2 2 条路径上取得的最大的和。

样例 #1

样例输入 #1
8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0
样例输出 #1
67

提示

数据范围: 1 ≤ N ≤ 9 1\le N\le 9 1N9

思路

如果该题只取一次数或者取走一次之后原来的数还在,就是一道简单的递推的题,但是该题需要来回取两次,如果我们按照贪心+递推的思想,取完一次之后修改方格中的数,然后再取一次,那么很容易举出反例,所以我们要思考其他办法。
我们要知道,无论是从A–>B还是从B–>A,对于取数的答案是不会有影响的,我们不妨看做从A–>B取数取两次,我们让这两次取数同时进行。
如果要同时表示表示这种状态就需要开四维数组dp[i][j][k][l],表示分别走到点(i,j)和(k,l)的最优解。
这种的思路还是比较好想的,代码如下

#include<bits/stdc++.h>
using namespace std;int mp[10][10],dp[10][10][10][10];
int main(){int n;cin>>n;while (1){int a,b,c;cin>>a>>b>>c;if (a==0&&b==0&&c==0)break;mp[a][b]=c;}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){for (int l=1;l<=n;l++){for (int k=1;k<=n;k++){dp[i][j][l][k]=max(max(dp[i-1][j][l-1][k],dp[i-1][j][l][k-1]),max(dp[i][j-1][l-1][k],dp[i][j-1][l][k-1]))+mp[i][j]+mp[l][k];if (i==l&&j==k)dp[i][j][l][k]-=mp[i][j];//如果相同则要减去一个}}}}cout<<dp[n][n][n][n];return 0;
}

因为这是2000年的题,那是的信息竞赛的水平不高,所以范围只有9,但是我们要有科学家钻研的品格(我们老师的梗),所以我们来探寻一下O(n3)的方法
不难想到我们可以发现,每当我们走一步,那么x坐标和y坐标之间总会有一个数加1所以,我们可以用k来表示x坐标和y坐标的和,从而通过y坐标来计算出x坐标。由于k对于两条同时处理的路径可以是公共的,所以我们就可以用 f [ k ] [ y 1 ] [ y 2 ] f[k][y1][y2] f[k][y1][y2]来表示当前状态。

#include<bits/stdc++.h>
using namespace std;int mp[700][700],dp[700][700][700];
int main(){int n;cin>>n;while (1){int a,b,c;cin>>a>>b>>c;if (a==0&&b==0&&c==0)break;mp[a][b]=c;}for (int i=1;i<=n+n;i++){for (int l=1;l<=min(i,n);l++){for (int k=1;k<=min(i,n);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[i-l][l]+mp[i-k][k];if (l==k)dp[i][l][k]-=mp[i-l][l];}}}cout<<dp[n+n][n][n];return 0;
}

[NOIP2008 提高组] 传纸条

题目传送门

题目描述

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排坐成一个 m m m n n n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标 ( 1 , 1 ) (1,1) (1,1),小轩坐在矩阵的右下角,坐标 ( m , n ) (m,n) (m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。

在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。

还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用 0 0 0 表示),可以用一个 [ 0 , 100 ] [0,100] [0,100] 内的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度之和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

输入格式

第一行有两个用空格隔开的整数 m m m n n n,表示班里有 m m m n n n 列。

接下来的 m m m 行是一个 m × n m \times n m×n 的矩阵,矩阵中第 i i i j j j 列的整数表示坐在第 i i i j j j 列的学生的好心程度。每行的 n n n 个整数之间用空格隔开。

输出格式

输出文件共一行一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

样例 #1

样例输入 #1

3 3
0 3 9
2 8 5
5 7 0

样例输出 #1

34

提示

【数据范围】

对于 30 % 30\% 30% 的数据,满足 1 ≤ m , n ≤ 10 1 \le m,n \le 10 1m,n10
对于 100 % 100\% 100% 的数据,满足 1 ≤ m , n ≤ 50 1 \le m,n \le 50 1m,n50

【题目来源】

NOIP 2008 提高组第三题。

思路

这道题其实和上一道题差不多,所以我们直接写代码,值得注意的是,这里的每一个人都是正数,所以不用考虑走了一次后就不能走了的情况,基本上可以完全参照上一道题的写法

#include<bits/stdc++.h>
using namespace std;long long mp[120][120],dp[120][120][120];
int main(){int n,m;cin>>n>>m;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){cin>>mp[i][j];}}for (int i=2;i<=n+m-1;i++){for (int l=1;l<=min(i,n);l++){for (int k=1;k<=min(i,n);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[l][i-l+1]+mp[k][i-k+1];if (l==k)dp[i][l][k]-=mp[l][i-l+1];}}}cout<<dp[n+m-1][n][n];return 0;
}

但是话又说回来,如果这道题是有负数的呢?那么我们就要考虑如何排除又重复的情况了。其实解题思路是一样的,只是状态转移方程不同,既然两条路径不能重叠,那么一定有一条路径在上上,一条路径在下方,这里我们始终让i<j就行了,但是注意特判起点和终点。

#include<bits/stdc++.h>
using namespace std;long long mp[220][220],dp[420][220][220];
int main(){int n,m;cin>>n>>m;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){cin>>mp[i][j];}}dp[2][1][1]=mp[1][1];for (int i=2;i<=n+m;i++){for (int j=0;j<=n;j++){for (int k=0;k<=n;k++){dp[i][j][k]=INT_MIN;}}}dp[2][1][1]=mp[1][1];for (int i=2;i<=n+m;i++){for (int l=1;l<=n&&l<i;l++){for (int k=1;k<min(l,i);k++){dp[i][l][k]=max(max(dp[i-1][l-1][k],dp[i-1][l][k]),max(dp[i-1][l][k-1],dp[i-1][l-1][k-1]))+mp[l][i-l]+mp[k][i-k];}}}dp[n+m][n][n]=dp[n+m-1][n][n-1]+mp[n][m];cout<<dp[n+m][n][n];return 0;
}

最大加权矩形

题目传送门

题目描述

为了更好的备战 NOIP2013,电脑组的几个穿黑丝的女孩子 LYQ,ZSC,ZHQ 认为,我们不光需要机房,我们还需要运动,于是就决定找校长申请一块电脑组的课余运动场地,听说她们都是电脑组的高手,校长没有马上答应他们,而是先给她们出了一道数学题,并且告诉她们:你们能获得的运动场地的面积就是你们能找到的这个最大的数字。

校长先给他们一个 n × n n\times n n×n 矩阵。要求矩阵中最大加权矩形,即矩阵的每一个元素都有一权值,权值定义在整数集上。从中找一矩形,矩形大小无限制,是其中包含的所有元素的和最大 。矩阵的每个元素属于 [ − 127 , 127 ] [-127,127] [127,127] ,例如

 0 –2 –7  0 9  2 –6  2
-4  1 –4  1 
-1  8  0 –2

在左下角:

9  2
-4  1
-1  8

和为 15 15 15

几个女孩子有点犯难了,于是就找到了电脑组精打细算的 HZH,TZY 小朋友帮忙计算,但是遗憾的是他们的答案都不一样,涉及土地的事情我们可不能含糊,你能帮忙计算出校长所给的矩形中加权和最大的矩形吗?

输入格式

第一行: n n n,接下来是 n n n n n n 列的矩阵。

输出格式

最大矩形(子矩阵)的和。

样例 #1

样例输入 #1

4
0 -2 -7 09 2 -6 2
-4 1 -4  1 
-1 8  0 -2

样例输出 #1

15

提示

1 ≤ n ≤ 120 1 \leq n\le 120 1n120

首先可以看到这道题的数据范围似乎不是很大,好像O(n4)就可以过,那么我们就先这样去想想,是不是可以利用前缀和呢?答案是可以的,代码如下

#include<iostream>
using namespace std;
int n,mx=INT_MIN;
int a[130][130],sum[130][130],qz[130][130];
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];qz[i][j]=qz[i][j-1]+a[i][j];sum[i][j]=qz[i][j]+sum[i-1][j];}}for(int x1=1;x1<=n;x1++){for(int y1=1;y1<=n;y1++){for(int x2=1;x2<=n;x2++){for(int y2=1;y2<=n;y2++){if (x2<x1||y2<y1)continue;mx=max(mx,sum[x2][y2]+sum[x1-1][y1-1]-sum[x2][y1-1]-sum[x1-1][y2]);}}}}cout<<mx;return 0;
}

但是我们再想想,如果数据再大一点怎么办呢?请听下回分解~~~~
![在这里插入图片描述](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https://cn.bing.com/images/search?view=detailV2&ccid=w5Af3r7K&id=4BDD3F5C94C39BC3D12D5CEA1528744455BBAC1D&thid=OIP.w5Af3r7KPyEO56el6hRklgHaKd&mediaurl=https%253a%252f%252fts1.cn.mm.bing.net%252fth%252fid%252fR-C.c3901fdebeca3f210ee7a7a5ea146496%253frik%253dHay7VUR0KBXqXA%2526riu%253dhttp%25253a%25252f%25252fcomic.people.com.cn%25252fmediafile%25252f201112%25252f26%25252请添加图片描述请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/42822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前后端分离系统

前后端分离是一种现代软件架构模式&#xff0c;特别适用于Web应用开发&#xff0c;它强调将用户界面&#xff08;前端&#xff09;与服务器端应用逻辑&#xff08;后端&#xff09;相分离。两者通过API接口进行数据交互。这种架构模式的主要优势在于提高开发效率、维护性和可扩…

Git命令常规操作

目录 常用操作示意图 文件的状态变化周期 1. 创建文件 2. 修改原有文件 3. 删除原有文件 没有添加到暂存区的数据直接 rm 删除即可&#xff1a; 对于添加到暂存区的数据 文件或目录&#xff1a; 4. 重命名暂存区数据 5. 查看历史记录 6. 还原历史数据 恢复过程的原…

最新深度技术Win7精简版系统:免费下载!

在Win7电脑操作中&#xff0c;用户想要给电脑安装上深度技术Win7精简版系统&#xff0c;但不知道去哪里才能找到该系统版本&#xff1f;接下来系统之家小编给大家带来了深度技术Win7系统精简版本的下载地址&#xff0c;方便大家点击下载安装。系统安装步骤已简化&#xff0c;新…

定位和分析解决std::thread创建失败的问题和解决方法(mmap虚拟地址耗尽)

文章目录 引言问题描述和分析监控shell脚本shell脚本解释 问题根源追溯解决方案一&#xff1a;增大mmap区域解决方案二&#xff1a;优化线程栈空间解决方案三&#xff1a;引入线程池参考文章 引言 在高并发和长周期运行的环境中&#xff0c;频繁创建std::thread线程可能导致mm…

设计模式8-桥模式

设计模式8-Bridge 桥模式 由来与目的模式定义结构代码推导1. 类和接口的定义2. 平台实现3. 业务抽象4. 使用示例总结1. 类数量过多&#xff0c;复杂度高2. 代码重复3. 不符合单一职责原则4. 缺乏扩展性改进后的设计1. 抽象和实现分离&#xff08;桥接模式&#xff09;2. 抽象类…

学习XDMA—20240709

概览&#xff1a; 在内部&#xff0c;子系统可以配置为实现多达8个独立的物理DMA引擎(最多4个H2C和4个C2H)。这些DMA引擎可以映射到单独的AXI4Stream接口&#xff0c;也可以将共享的AXI4内存映射(MM)接口映射到用户应用程序。在axis4 MM接口上&#xff0c;PCI Express的DMA/桥接…

智能警卫:Conda包依赖的自动监控之道

智能警卫&#xff1a;Conda包依赖的自动监控之道 引言 在复杂的软件开发项目中&#xff0c;依赖管理是确保项目健康运行的关键环节。Conda作为Python和其他科学计算语言的强大包管理器&#xff0c;提供了依赖监控功能&#xff0c;帮助用户自动化和简化依赖项的监控过程。本文…

软考高级第四版备考--第15天(建设团队)Develop Team

定义&#xff1a;提高工作能力&#xff0c;促进团队成员互动&#xff0c;改善团队整体氛围以提高项目绩效的过程 作用&#xff1a;改进团队协作、增强人际关系技能、激励员工、减少摩擦以提升整体项目绩效 说明&#xff1a;高效团队行为&#xff1a; 使用开放与有效的沟通&a…

简述 JS 中对象的创建和拷贝

在 JavaScript 中&#xff0c;对象是一种非常重要且灵活的数据结构&#xff0c;用于存储多个值&#xff08;属性&#xff09;和方法&#xff08;函数&#xff09; 对象的创建和拷贝是日常开发中经常涉及的操作&#xff0c;对于业务逻辑的准确实现有着重要的作用 本文将简要概…

linux查看目录下的文件夹命令,find 查找某个目录,但是不包括这个目录本身?

linux查看目录下的文件夹命令&#xff0c;find 查找某个目录&#xff0c;但是不包括这个目录本身&#xff1f; Linux中查看目录下的文件夹的命令是使用ls命令。ls命令用于列出指定目录中的文件和文件夹。通过不同的选项可以实现显示详细信息、按照不同的排序方式以及使用不同的…

Profibus转ModbusTCP网关模块实现Profibus_DP向ModbusTCP转换

Profibus和ModbusTCP是工业控制自动化常用的二种通信协议。Profibus是一种串口通信协议&#xff0c;它提供了迅速靠谱的数据传输和各种拓扑结构&#xff0c;如总线和星型构造。Profibus可以和感应器、执行器、PLC等各类设备进行通信。 ModbusTCP是一种基于TCP/IP协议的通信协议…

一次零基础 自“信息收集“到“权限维持“的渗透测试全程详细记录

一、渗透总流程 1.确定目标&#xff1a; 在本靶场中&#xff0c;确定目标就是使用各种扫描工具进行ip扫描&#xff0c;确定目标ip。 2.信息收集&#xff1a; 比如平常挖洞使用fofa&#xff0c;天眼查&#xff0c;ip域名等进行查&#xff0c;在我们这个靶场中比如使用Wappalyz…

基于网络编码的 tcp 变种-tcp/nc

tcp/nc 是指 “tcp with network coding”&#xff0c;是一种结合了网络编码技术的 tcp 变种&#xff0c;网上资源很少&#xff0c;我也不准备多介绍&#xff0c;只介绍它的核心。 传统 tcp 在演进过程中一直搞不定效率问题&#xff0c;网络带宽在增长&#xff0c;cpu 却没有变…

C++类和对象(上篇)

文章目录 前言一、面向过程和面向对象初步认识 二、类的引入 三、类的定义 六、类的实例化 七、类的对象大小的计算 八、类成员函数的this指针 总结 前言 类和对象是面向对象编程的两个核心概念。 类是一种抽象的数据类型&#xff0c;是描述对象共同特征和行为的模板。一个类…

yolov5:Conv类参数量计算

Conv是yolov5自定义的类&#xff0c;里边包含了卷积层、BN层和激活函数 class Conv(nn.Module):# Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)default_act nn.SiLU() # default activationdef __init__(self, c…

点云下采样有损压缩

转自本人博客&#xff1a;点云下采样有损压缩 点云下采样是通过一定规则对原点云数据进行再采样&#xff0c;减少点云个数&#xff0c;降低点云稀疏程度&#xff0c;减小点云数据大小。 1. 体素下采样&#xff08;Voxel Down Sample&#xff09; std::shared_ptr<PointClo…

华为机考真题 -- 信道分配

题目描述&#xff1a; 算法工程师小明面对着这样一个问题&#xff0c;需要将通信用的信道分配给尽量多的用户&#xff0c; 信道的条件及分配规则如下&#xff1a; 1) 所有信道都有属性&#xff1a;”阶”。阶为 r 的信道容量为 2^r 比特&#xff1b; 2) 所有用户需要传输的数…

区间贪心

目录 1.贪心算法的思想 2.区间贪心算法常用的一些题目类型 1.选择最多不相交区间问题 P2970 [USACO09DEC] Selfish Grazing S 1.思路分析 2.上代码 2.区间选点问题 P1250 种树 1.题目 2.方法一 1.代码解释 3.方法二 3.区间合并问题 P2434 [SDOI2005] 区间 1. 思路…

中科海讯 C++初级研发工程师笔试题目

C语言中的const关键字有什么作用&#xff1f;为什么要使用const关键字&#xff1f; 1 const修饰的变量将会被放到常量区&#xff0c;避免被意外的改动。 const修饰的常量比#define修饰的有更多的优势&#xff0c;比如可以调试&#xff0c;类型检查等 2 const修饰的参数可做输入…

Java集合面试题

Java集合框架 1、List、Set、Map的区别2、ArrayList、LinkedList、Vector区别3、为什么数组索引从0开始&#xff0c;而不是从1开始&#xff1f;4、ArrayList底层的实现原理5、红黑树、散列表6、HashMap的底层原理7、HashMap的put方法具体流程8、HashMap的扩容机制9、HashMap是怎…