**摘要:**本题要求在二维平面内给定 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;
}