ABC369F F - Gather Coins 题解
题目链接:https://atcoder.jp/contests/abc369/tasks/abc369_f
题目大意:
在一个 的二维迷宫中有 枚硬币,其中第 枚硬币在 (本题中,我们用 表示二维迷宫中从上到下第 行从左到右第 列的那个格子)。
你一开始在迷宫的左上角 处,你要移动到一共的右下角 ,但是你每次移动智能向右或向下移动一格。
求:路径上最多能够收集到的硬币数?同时,还要求输出任意一种满足条件的移动方案。
数据范围:
- 各不相同
题解
将所有有硬币的位置 按升序排序。
这里我们定义 当且仅当 或者 的情况下 。
我们假设最终移动的过程中依次手机到的硬币的位置构成的序列为:,,……,。
很明显 。
所以答案就是对 排序之后对 求 LIS(这里是最长飞将子序列),求 LIS 的同时记录一下路径即可。
示例程序:
https://atcoder.jp/contests/abc369/submissions/57359342
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int H, W, n, f[maxn], m, pos[maxn], pre[maxn], ans;
struct Node {
int r, c;
bool operator < (const Node &b) const {
return r < b.r || r == b.r && c < b.c;
}
} a[maxn];
int main() {
scanf("%d%d%d", &H, &W, &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].r, &a[i].c);
sort(a+1, a+n+1);
for (int i = 1; i <= n; i++) {
int p = upper_bound(f, f+m, a[i].c) - f;
if (p == m) m++;
f[p] = a[i].c;
pos[p] = i;
if (p)
pre[i] = pos[p-1];
}
printf("%d\n", m);
vector<Node> vec;
vec.push_back({H, W});
for (int i = pos[m-1]; i; i = pre[i])
vec.push_back({a[i].r, a[i].c});
vec.push_back({1, 1});
assert(vec.size() == m+2);
reverse(vec.begin(), vec.end());
for (int i = 0; i+1 < m+2; i++) {
int cnt_d = vec[i+1].r - vec[i].r, cnt_r = vec[i+1].c - vec[i].c;
while (cnt_d--) putchar('D');
while (cnt_r--) putchar('R');
}
return 0;
}
标签:
LIS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现