【SSL 1956】【CSP/J 2022 T4】 上升点列(DP)

题目大意

    在一个二维平面内,给定 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

【输入样例2】
4 100
10 10
15 25
20 20
30 30

输出样例

【输出样例1】
8

【输出样例2】
103

基本思路

这题似乎没那么容易看出来是道DP。

不能往下走,这就是无后效性。仔细理解理解。

我们要在原有的节点中间添加点使其联通。

f[i][p]意为在第i个点前添加p个点所能得到的最大距离。

核心代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=510;
struct node{
	int xi,yi;
}a[N];
int n,k,f[N][110],ans;
bool cmp(node a,node b){
	if(a.xi!=b.xi) return a.xi<b.xi;
	return a.yi<b.yi;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i].xi>>a[i].yi;
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){//第i个点 
		ans=max(ans,k+1);
		for(int p=0;p<=k;p++){//添加p个点 
			f[i][p]=p+1;//初始化 在自己前加p个点 
			for(int j=1;j<i;j++){//向前判断与前面的点的关系 
				int d=abs(a[i].xi-a[j].xi)+abs(a[i].yi-a[j].yi)-1;//判断缺了多少个点 
				if(a[i].yi<a[j].yi||d>p) continue;
				f[i][p]=max(f[i][p],f[j][p-d]+(d+1));
			}
			ans=max(ans,f[i][p]);
		}
		/*
		ans存在哪呢?
		注意一个神奇的数据:
		两个点隔得极其远,远到无法用k填补,
		于是只能在各自前加k个点 
		*/
	}
	cout<<ans;
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值