题目大意
在一个二维平面内,给定 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;
}