4139: 上升点列 [CSP-J 2022]

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:1 解决:1

题目描述

在一个二维平面内,给定 lns="http://www.w3.org/1998/Math/MathML"> 个整数点 lns="http://www.w3.org/1998/Math/MathML">(,),此外你还可以自由添加 lns="http://www.w3.org/1998/Math/MathML"> 个整数点。

你在自由添加 lns="http://www.w3.org/1998/Math/MathML"> 个点后,还需要从 lns="http://www.w3.org/1998/Math/MathML">+ 个点中选出若干个整数点并组成一个序列,使得序列中任意相邻两点间的欧几里得距离恰好为 lns="http://www.w3.org/1998/Math/MathML">1 而且横坐标、纵坐标值均单调不减,即 lns="http://www.w3.org/1998/Math/MathML">lns="http://www.w3.org/1998/Math/MathML">+1lns="http://www.w3.org/1998/Math/MathML">=1lns="http://www.w3.org/1998/Math/MathML">lns="http://www.w3.org/1998/Math/MathML">+1lns="http://www.w3.org/1998/Math/MathML">= 或 lns="http://www.w3.org/1998/Math/MathML">lns="http://www.w3.org/1998/Math/MathML">+1lns="http://www.w3.org/1998/Math/MathML">=1,lns="http://www.w3.org/1998/Math/MathML">+1lns="http://www.w3.org/1998/Math/MathML">=。请给出满足条件的序列的最大长度。

输入

第一行两个正整数 lns="http://www.w3.org/1998/Math/MathML">, 分别表示给定的整点个数、可自由添加的整点个数。

接下来 lns="http://www.w3.org/1998/Math/MathML"> 行,第 lns="http://www.w3.org/1998/Math/MathML"> 行两个正整数 lns="http://www.w3.org/1998/Math/MathML">, 表示给定的第 lns="http://www.w3.org/1998/Math/MathML"> 个点的横纵坐标。

输出

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

样例输入 复制

8 2
3 1
3 2
3 3
3 6
1 2
2 2
5 5
5 3

样例输出 复制

8

提示

【数据范围】

保证对于所有数据满足:lns="http://www.w3.org/1998/Math/MathML">1500lns="http://www.w3.org/1998/Math/MathML">0100。对于所有给定的整点,其横纵坐标 lns="http://www.w3.org/1998/Math/MathML">1,109,且保证所有给定的点互不重合。对于自由添加的整点,其横纵坐标不受限制。

#include<bits/stdc++.h>
using namespace std;
const int maxn=500+10;
const int maxk=100+10;
int n, k;
pair<int,int> a[maxn];
int f[maxn][maxk]; 
/*
f[i][j]表示以第i个点为结尾(即右上角)且允许添加j个点时的最长答案。
转移时,枚举点i之前添加哪个节点,遍历所有其他点即可。
时间复杂度O(n*n*k)
*/
int main(){
    //freopen("point.in","r",stdin);
    //freopen("point.out","w",stdout);
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n; i++) scanf("%d%d",&a[i].first, &a[i].second);
    sort(a+1,a+n+1);
    for(int i=1; i<=n; i++)
        for(int j=0;j<=k; j++){
            f[i][j]=j+1;
            for(int p=1; p<i; p++)
                if(a[p].first<=a[i].first && a[p].second<=a[i].second){
				    int d=a[i].first -a[p].first + a[i].second - a[p].second - 1;
                    if(d<=j) f[i][j]= max(f[i][j],f[p][j-d]+d+1);
            }
        }
    int ans =0;
    for(int i=1;i<=n; i++) ans = max(ans, f[i][k]);
    printf("%d\n", ans);
    return 0;
}