《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;
}
相关推荐
NEFU_Jyj17 小时前
牛客周赛R168
算法
likexuec1 天前
数据结构(2)
数据结构
Navigator_Z1 天前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
D e re k ZH1 天前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶1 天前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
雪落漂泊1 天前
C++算法 二分查找篇(上)
开发语言·c++·算法
LabVIEW开发1 天前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
严肃小白兔1 天前
MATLAB 数值计算中的精度与误差问题:浮点运算、误差传播与数值稳定性
人工智能·算法·matlab
青少儿编程课堂1 天前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛