洛谷 P8816 [CSP-J 2022] 上升点列(T4)

目录

题目传送门

算法解析

最终代码

提交结果

尾声


题目传送门

[CSP-J 2022] 上升点列 - 洛谷icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P8816

算法解析

k = 0 且 xi, yi 值域不大时,这题是非常简单的 DP,类似「数字三角形」。

记 dp(x,y) 为「以 (x,y) 为终点,最长合法序列的长度」。

则对于所有(已经存在的)整点,有:

dp(x,y) = max {dp(x − 1, y), dp(x, y − 1)} + 1

xi, yi 值域比较大时:

可以考虑记 dp(n) 表示「以 n 号点结尾的合法序列,最长能有多长」。

dp(n) = max {dp(i) + 1}

i → n ✓

不会存在环状结构——因为合法序列必须向右、上方发展。

把刚刚的DP改造一下,就是本题正解:

记 dp(n, k) 表示「以 n 号点结尾,已经使用掉了 k 个自由点,获得的收益」。

dp(n,k) = max {dp(i, k − cost) + cost + 1}

i → n ✓

实现细节:本题的求值顺序值得注意,合法路径可能形如 P1 → P3 → P2。

有两种解决方法:

  • 记忆化搜索(记忆化搜索最擅长解决求值顺序混乱的 DP)
  • 预先按 x, y 排序,使得编号大的点一定是从编号小的点转移过来

这里记忆化搜索比较好写一些,我这里就只讲记忆化搜索了

先写一下求 a 到 b 需要补多少个点的函数,即两点曼哈顿距离再减一(a 在左下,b 在右上,否则返回无穷)

代码中 x[u] 表示 u 点的横坐标,y[u] 表示 u 点的纵坐标

int dis(int a, int b) {if(x[a] > x[b])return inf;if(y[a] > y[b])return inf;return x[b] - x[a]  + y[b] - y[a] - 1;
}

然后是 dp 函数,定义上面已经说过了

int dp(int now, int k)

首先判断如果自由点已经用完了,即 k < 0,那么返回负无穷(因为最后是取最大值)

int dp(int now, int k) {if(k < 0)return -inf;
}

既然是记忆化,那么就需要记忆

用 vis[n][k] 数组记录 dp(n, k) 是否访问过,val[n][k] 数组记录如果访问过的 dp(n, k) 的值

这样如果 vis[now][k] == true(访问过),则返回 val[now][k]

int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];
}

然后就该枚举它的前驱(代码中的 to),然后取里面最大的收益

这个记录最大收益的变量(代码中的 res)的初值一定要是 1,因为如果哪也去不了,那么就只能走到现在这一个点,也就是 now

int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)return res;
}

接下来需要判断 to != now,然后计算出 to 到 now 需要补多少个点(代码中的 cost)

int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)if(to != now) {int cost = dis(to, now);}return res;
}

再判断费用超出运算,就 contunue(如果走不到,dis 就会返回无穷,一定大于 k,所以不用特判走不到)

int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)if(to != now) {int cost = dis(to, now);if(cost > k)continue;}return res;
}

接着就是往下递归了,now 变成了 to,预算费用还剩 k - cost,所以传进去是

dp(to, k - cost)

然后长度还需要加上 to 到 now 的距离,即 cost + 1,然后更新最大值(代码里的 res)

代码中的 bemax 函数是把第一个参数赋成两个参数的最大值用的,具体实现方法就是用一个三目运算符

void bemax(int &a, int b) {a = a > b ? a : b;
}
int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)if(to != now) {int cost = dis(to, now);if(cost > k)continue;bemax(res, dp(to, k - cost) + cost + 1);}return res;
}

最后再将 vis[now][k] 设成 true,val[now][k] 设成 res

最后 return res 就行了

int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)if(to != now) {int cost = dis(to, now);if(cost > k)continue;bemax(res, dp(to, k - cost) + cost + 1);}vis[now][k] = true;val[now][k] = res;return res;
}

主函数里需要枚举 i = 1 ~ n,j = 0 ~ k,然后传进去(n 为点的个数,k 为自由点的个数)

注意长度还需要加上没用的 k - j 个点,然后更新答案(代码中的 ans)

for(int i = 1; i <= n; ++i)for(int j = 0; j <= k; ++j)bemax(ans, dp(i, j) + k - j);

最后输出 ans 即可 

最终代码

#include <cstdio>
#define N 1005
using namespace std;const int inf = 0x7fffffff;int n, k;
int x[N], y[N];
bool vis[N][N];
int val[N][N];
int ans;void bemax(int &a, int b) {a = a > b ? a : b;
}int dis(int a, int b) {if(x[a] > x[b])return inf;if(y[a] > y[b])return inf;return x[b] - x[a]  + y[b] - y[a] - 1;
}int dp(int now, int k) {if(k < 0)return -inf;if(vis[now][k])return val[now][k];int res = 1;for(int to = 1; to <= n; ++to)if(to != now) {int cost = dis(to, now);if(cost > k)continue;bemax(res, dp(to, k - cost) + cost + 1);}vis[now][k] = true;val[now][k] = res;return res;
}int main() {scanf("%d%d", &n, &k);for(int i = 1; i <= n; ++i)scanf("%d%d", &x[i], &y[i]);for(int i = 1; i <= n; ++i)for(int j = 0; j <= k; ++j)bemax(ans, dp(i, j) + k - j);printf("%d\n", ans);return 0;
}

提交结果

提交一下哈

㇏(〃'▽'〃)㇀ AC ! ! !

尾声

如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!

最后,祝您(您的团队)在 OI 的路上一路顺风!!!

┬┴┬┴┤・ω・)ノ Bye~Bye~

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

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

相关文章

tomcat基础介绍

目录 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; 2、Tomcat的配置文件详解 3、Tomcat的构成组件 6、Tomcat的请求过程 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器…

植物病虫害:YOLO玉米病虫害识别数据集

玉米病虫害识别数据集&#xff1a;玉米枯萎病&#xff0c;玉米灰斑病&#xff0c;玉米锈病叶&#xff0c;粘虫幼虫&#xff0c;玉米条斑病&#xff0c;黄二化螟&#xff0c;黄二化螟幼虫7类&#xff0c;yolo标注完整&#xff0c;3900多张图像&#xff0c;全部原始数据&#xff…

二、TensorFlow结构分析(4)

TF数据流图图与TensorBoard会话张量Tensor变量OP高级API 目录 1、变量 2、高级API 1、变量 2、高级API

RFID技术进阶:频段选择的艺术与科学

RFID技术进阶&#xff1a;频段选择的艺术与科学 在数字化、自动化的浪潮中&#xff0c;RFID&#xff08;无线射频识别&#xff09;技术以其独特的优势&#xff0c;逐渐在多个领域占据了一席之地。RFID&#xff08;Radio Frequency Identification&#xff09;&#xff0c;即无…

24/03/07总结

esayx: 贪吃蛇: #include "iostream" #include "cmath" #include "conio.h" #include "easyx.h" #include "time.h" #define NODE_WIDTH 40 using namespace std; typedef struct {int x;int y; }node; enum direction /…

C++ Lambda函数

lambda语法 [capture list] (parameter list) specifiers exception -> type { function body }[capture list]是捕获列表&#xff0c;在应用中必填。 (parameter list)是参数列表&#xff0c;在应用中选填。 specifiers是限定符&#xff0c;在应用中选填。 exception是…

Java对接腾讯云直播示例

首先是官网的文档地址 云直播 新手指南 可以发现它这个主要是按流量和功能收费的 价格总览 流量这里还只收下行的费用&#xff0c;就是只收观看消耗的流量费 其它的收费就是一些增值业务费 &#xff08;包括直播转码、直播录制、直播截图、直播审核、智能鉴黄、实时监播、移动直…

【性能测试】Jmeter性能压测-阶梯式/波浪式场景总结(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、阶梯式场景&am…

学习JAVA的第十四天(基础)

目录 Collection集合 迭代器遍历 增强for遍历 Lambda表达式遍历 List集合 遍历 数据结构 栈 队列 数组 链表 前言&#xff1a; 学习JAVA的第十三天 Collection集合 Collection的遍历方式&#xff1a; 迭代器&#xff08;不依赖索引&#xff09;遍…

爱普生宣布开发出独特的宽幅度LVDS输出 —可灵活选择与LSI

爱普生宣布开发出独特的宽幅度LVDS输出 —可灵活选择与LSI -相匹配的低噪声输出 精工爱普生公司(TSE: 6724&#xff0c;“爱普生”)开发了一种新的晶体振荡器差分输出方案。新方案&#xff0c;宽幅低压差分信号(WA-LVDS)&#xff0c;可以灵活选择最适合LSI所需的幅值水平的输出…

浅谈碳化硅MOSFET TO-247封装单管引入开尔文管脚必要性

相较于传统的硅MOSFET和硅IGBT 产品&#xff0c;基于宽禁带碳化硅材料设计的碳化硅 MOSFET 具有耐压高、导通电阻低&#xff0c;开关损耗小的特点&#xff0c;可降低器件损耗、减小产品尺寸&#xff0c;从而提升系统效率。而在实际应用中&#xff0c;我们发现&#xff1a;带辅助…

外包干了一个月,技术退步明显。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这次来聊一个大家可能也比较关心的问题&#xff0c;那就是就业城…

Sora的双重边缘:视频生成的革新与就业的再思考

随着科技的日新月异&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术如潮水般涌入我们的日常生活&#xff0c;为各个领域带来了翻天覆地的变化。在这一浪潮中&#xff0c;Sora作为一款前沿的AI视频生成工具&#xff0c;凭借其高度逼真…

MindOpt优化器: 浅谈版本0.x和1.x之间API的差异

Mindopt 是一个优化求解器&#xff0c;如果它有两个主要版本——0.xx和1.x.x&#xff08;最新版本1.1.1&#xff09;&#xff0c;它们代表着软件开发的两个不同阶段。版本1.0.0表示软件的一个大的里程碑&#xff0c;代表着软件第一个正式的“成熟”发布版本&#xff0c;而0.25是…

MySQL--优化(索引--索引失效场景)

MySQL–优化&#xff08;索引–索引失效场景&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 常见的索引失效场景 1、场景准备&#xff1a; 给 tb_user 表创建联合索引&#xff0c;字段为&#xff1…

消息队列-Kafka-消费方如何分区与分区重平衡

消费分区 资料来源于网络 消费者订阅的入口&#xff1a;KafkaConsumer#subscribe 消费者消费的入口&#xff1a;KafkaConsumer#poll 处理流程&#xff1a; 对元数据重平衡处理&#xff1a;KafkaConsumer#updateAssignmentMetadataIfNeeded 协调器的拉取处理&#xff1a;onsum…

linux下改变主机名,永久生效的方法

hostnamectl set-hostname test 例子 #支持大写必须就要这样写 hostnamectl set-hostname 名称 --static

缩放算法优化步骤详解

添加链接描述 背景 假设数据存放在在unsigned char* m_pData 里面&#xff0c;宽和高分别是&#xff1a;m_nDataWidth m_nDataHeight 给定缩放比例&#xff1a;fXZoom fYZoom&#xff0c;返回缩放后的unsigned char* dataZoom 这里采用最简单的缩放算法即&#xff1a; 根据比…

代理IP以及动态拨号VPS的关系是什么?

在数字时代&#xff0c;网络安全和隐私保护已成为全球关注的热点话题。代理IP和动态拨号VPS作为提升网络匿名性和安全的重要技术&#xff0c;它们在维护网络隐私中扮演着至关重要的角色。虽然这两种技术在表面上看似相似&#xff0c;实际上它们在功能、应用场景以及用户需求满足…

react + antdesign table组件合并行,展开子表格

假如你有这样的一个数据&#xff1a; [{"bigClass":"吃的","smallClass":"水果","item":"苹果"},{"bigClass":"吃的","smallClass":"水果","item":"香蕉…