CCC2014 S5 Lazy Fox 题解

题目传送门
Problem Description
You have a pet Fox who loves treats. You have N neighbours at distinct locations (described as
points on the Cartesian plane) which hand out treats to your pet Fox, and each neighbour has an
unlimited number of treats to give out. The origin (which is where the Fox starts) will not be one
of these N locations.
What does the Fox say, in order to get these treats? That is a good question, but not our concern.
The Fox moves from location to location to gather exactly one treat from each location on each
visit. He can revisit any previous location, but cannot visit the same location on two consecutive
visits.
Your Fox is very lazy. The distance your Fox is willing to travel after each treat will strictly
decrease. Specifically, the distance from the origin to his first treat location must be larger than the
distance from his first treat location to his second treat location, which in turn is larger than the
distance between his second treat location and his third treat location, and so on.
What is the largest number of treats your Fox gathers?
Input Specification
The first line contains the integer N (1 ≤ N ≤ 2000). The next N lines each contain Xi
, followed
by a space, followed by Yi
, for i = 1..N (−10 000 ≤ Xi
, Yi ≤ 10 000) representing the coordinates
of the ith location. The following additional constraints will apply.

  • At least 20% of the marks will be for test cases where N ≤ 50;
  • at least 40% of the marks will be for test cases where N ≤ 200;
  • the remaining marks will be for test cases where N ≤ 2000.

Output Specification
The output is one integer, the largest number of treats your Fox can gather.
Sample Input

5
5 8
4 10
3 1
3 2
3 3

Output for Sample Input

6
10

Explanation of Output for Sample Input
The Fox performs the visits in the following order (with the indicated distances):
• (0, 0) to (4, 10) with distance \(\sqrt{116}\);
• (4, 10) to (3, 1) with distance \(\sqrt{82}\);
• (3, 1) to (5, 8) with distance \(\sqrt{53}\);
• (5, 8) to (3, 3) with distance \(\sqrt{29}\);
• (3, 3) to (3, 1) with distance 2;
• (3, 1) to (3, 2) with distance 1.

题目翻译
在平面直角坐标系上有 \(N\) 个点,给出这些点的坐标,求从原点出发,最多的经过几个点。(要求经过的点两点之间的欧几里得距离严格递减)


题目解析
感觉就是一个带限制的最长路。
利用bellman ford(就是SPFA的退化版)来求出最短路。
先把所有的边排序,然后把这些边逐个操作,最后经过bellman ford的松弛操作,即可得出答案。
具体的细节见注释。

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 20039
#define js(x) ((x)*(x))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
typedef int Type;
inline Type read(void){
	Type sum=0;
	int flag=0;
	char c=getchar();
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') c=getchar(),flag=1;
	while('0'<=c&&c<='9'){
		sum=(sum<<1)+(sum<<3)+(c^48);
		c=getchar();
	}
	if(flag) return -sum;
	return sum;
}
struct JTZ{
	int dist,x,y;
	bool operator < (const JTZ x) const{
		return this->dist< x.dist;
	}
};
vector<JTZ> dist;
int x[maxn],y[maxn];
int pd[maxn],ans[maxn],pa[maxn];
//ans[i]代表起点为i的最大数值,i=0的时候就是原点
int n,m,maxx;
int d,a,b;
int main(){
    n=read();
    register int i,j;
    for(i=1;i<=n;i++){
    	x[i]=read();
    	y[i]=read();
	}
	for(i=0;i<n;i++)
	    for(j=i+1;j<=n;j++)
	        dist.push_back((JTZ){js(x[i]-x[j])+js(y[i]-y[j]),i,j});
	sort(dist.begin(),dist.end());//排序
	m=dist.size();
	for(i=0;i<m;i++){
		d=dist[i].dist;
		a=dist[i].x;
		b=dist[i].y;
		if(d!=pd[a]){//题目要求严格递减,这里把相等的去掉
			pd[a]=d;
			pa[a]=ans[a];
		}
		if(d!=pd[b]){//同上
			pd[b]=d;
			pa[b]=ans[b];
		}
		if(a==0){//注意0号点就是起点
			ans[a]=max(ans[a],pa[b]);
		}
		else{
			ans[a]=max(ans[a],pa[b]+1);
			ans[b]=max(ans[b],pa[a]+1);
		}
	}
	printf("%d",ans[0]+1);//加上第一个点的数量
	return 0;
}

Update10.8:

vector比较慢,这里再放一份用数组的代码。

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2039
#define js(x) ((x)*(x))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
typedef int Type;
inline Type read(void){
	Type sum=0;
	int flag=0;
	char c=getchar();
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') c=getchar(),flag=1;
	while('0'<=c&&c<='9'){
		sum=(sum<<1)+(sum<<3)+(c^48);
		c=getchar();
	}
	if(flag) return -sum;
	return sum;
}
struct JTZ{
	int dist,x,y;
	bool operator < (const JTZ x) const{
		return this->dist< x.dist;
	}
};
JTZ dist[maxn*maxn];
int x[maxn],y[maxn];
int pd[maxn],ans[maxn],pa[maxn];
int n,m,maxx;
int d,a,b,cnt;
int main(){
    n=read();
    register int i,j;
    for(i=1;i<=n;i++){
    	x[i]=read();
    	y[i]=read();
	}
	cnt=0;
	for(i=0;i<n;i++)
	    for(j=i+1;j<=n;j++)
	        dist[++cnt]=(JTZ){js(x[i]-x[j])+js(y[i]-y[j]),i,j};
	sort(dist+1,dist+cnt+1);
	for(i=1;i<=cnt;i++){
		d=dist[i].dist;
		a=dist[i].x;
		b=dist[i].y;
		if(d!=pd[a]){
			pd[a]=d;
			pa[a]=ans[a];
		}
		if(d!=pd[b]){
			pd[b]=d;
			pa[b]=ans[b];
		}
		if(a==0){
			ans[a]=max(ans[a],pa[b]);
		}
		else{
			ans[a]=max(ans[a],pa[b]+1);
			ans[b]=max(ans[b],pa[a]+1);
		}
	}
	printf("%d",ans[0]+1);
	return 0;
}

posted @ 2021-02-15 22:10  jiangtaizhe001  阅读(37)  评论(0编辑  收藏  举报