《P8816 [CSP-J 2022] 上升点列》

**摘要:**本题要求在二维平面内给定 n 个整数点,并允许自由添加 k 个点,从中选出若干点组成序列,使相邻点欧几里得距离为 1 且横纵坐标单调不减,求满足条件的序列最大长度。本文给出完整的题目描述、输入输出格式、样例数据、数据范围说明以及 C++ 参考实现。

题目描述

在一个二维平面内,给定 n 个整数点 (xi​,yi​),此外你还可以自由添加 k 个整数点。

你在自由添加 k 个点后,还需要从 n+k 个点中选出若干个整数点并组成一个序列,使得序列中任意相邻两点间的欧几里得距离恰好为 1 而且横坐标、纵坐标值均单调不减,即 xi+1​−xi​=1,yi+1​=yi​ 或 yi+1​−yi​=1,xi+1​=xi​。请给出满足条件的序列的最大长度。

输入格式

第一行两个正整数 n,k 分别表示给定的整点个数、可自由添加的整点个数。

接下来 n 行,第 i 行两个正整数 xi​,yi​ 表示给定的第 i 个点的横纵坐标。

输出格式

输出一个整数表示满足要求的序列的最大长度。

输入输出样例

输入 #1复制

复制代码
8 2
3 1
3 2
3 3
3 6
1 2
2 2
5 5
5 3

输出 #1复制

复制代码
8

输入 #2复制

复制代码
4 100
10 10
15 25
20 20
30 30

输出 #2复制

复制代码
103

说明/提示

【样例 #3】

见附件中的 point/point3.in 与 point/point3.ans。

第三个样例满足 k=0。

【样例 #4】

见附件中的 point/point4.in 与 point/point4.ans。

【数据范围】

保证对于所有数据满足:1≤n≤500,0≤k≤100。对于所有给定的整点,其横纵坐标 1≤xi​,yi​≤109,且保证所有给定的点互不重合。对于自由添加的整点,其横纵坐标不受限制。

测试点编号 n≤ k≤ xi​,yi​≤
1∼2 10 0 10
3∼4 10 100 100
5∼7 500 0 100
8∼10 500 0 109
11∼15 500 100 100
16∼20 500 100 109

附件下载

point.zip1.53KB

代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 505;
const int MAXK = 105;

struct Point {
    int x, y;
    bool operator<(const Point &other) const {
        if (x != other.x) return x < other.x;
        return y < other.y;
    }
}p[MAXN];

int dp[MAXN][MAXK];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, k;
    cin >> n >> k;
    for(int i = 1; i <= n; i++)
    {
        cin >> p[i].x >> p[i].y;
    }
    sort(p + 1, p + 1 + n);
    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= k; j++)
        {
            dp[i][j] = 1;
        }
        for(int pre = 1; pre < i; pre++)
        {
            if(p[pre].x > p[i].x || p[pre].y > p[i].y) continue;
            int dx = p[i].x - p[pre].x;
            int dy = p[i].y - p[pre].y;
            int need = dx + dy - 1;
            for(int j = k; j >= need; j--)
            {
                dp[i][j] = max(dp[i][j], dp[pre][j - need] + need + 1);
            }
        }
        for(int j = 0; j <= k; j++)
        {
            int total = dp[i][j] + (k - j);
            ans = max(ans, total);
        }
    }
    cout << ans << endl;
    return 0;
}
相关推荐
hetao17338371 小时前
2026-10-19 hetao1733837 的刷题记录
c++·算法
辛苦才能1 小时前
C++ 哈希表深度解析:删除为什么必须打标记,负载因子为什么卡 0.7
开发语言·数据结构·c++·算法
m0_639906941 小时前
HashMap:哈希扰动、扩容源码、红黑树转换、并发问题
java·算法·哈希算法
JasmineX-12 小时前
数据结构(笔记)——顺序栈
c语言·数据结构·笔记
开开心心就好3 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
凉茶钱3 小时前
list:哨兵节点,const_iterator 和 const iterator的区别与迭代器失效
数据结构·c++·list
Jsundoku4 小时前
第六章 机器学习 -- 支持向量机
算法·机器学习·支持向量机
?abc!4 小时前
(数组)448. 找到所有数组中消失的数字
算法