向前走莫回头❤

【NOIP 模拟题】独眼兔(计算几何)

独眼兔(aneye.cpp)

【问题描述】

  太郎有一只特殊的兔子,他只有一只左眼,所以当他移动时是不能向右移动的。一天,太郎跟独眼兔做一个游戏,太郎在平面内放了N个萝卜,每个萝卜有一个坐标(xi,yi),且任意两个萝卜不在同一位置。设萝卜A(xi,yi)的yi是所有萝卜中最小的,那么独眼兔从(0,yi)出发,走向萝卜A,然后开始吃萝卜。当他吃完一个萝卜后,会选择下一个萝卜为目标,然后径直向萝卜走去,当然他移动时是不能向右转弯的。独眼兔还有一个特点,他走过的路径上会留下特殊的气味,所以独眼兔不希望他将要走的路与前面走的路相交。太郎想知道独眼兔如何才能吃到最多的萝卜。

                                                                   

【问题输入】

  第一行是个整数N;接下来N行,每行两个整数,第i+1行表示第i号萝卜的位置(xi,yi)。

【问题输出】

  一行,输出最多能吃到的萝卜数,后面输出吃萝卜的顺序。

【样例输入】

   10

   4 5

   9 8

   5 9

   1 7

   3 2

   6 3

   10 10

   8 1

   2 4

   7 6

【样例输出】

  10 8 7 3 4 9 5 6 2 1 10

【数据范围】

  40%的数据:n<=100;

  100%数据:n<=1000,xi<=10000,yi<=10000

_______________________________________________________________________________________

【题解】【计算几何】

【通过分析题目可知,如果行走路线得当,所有萝卜都能吃到。】

【所以,在找下一个点的时候,要保证有尽量多的点在当前点的逆时针方向,依据这个条件不停更新。判断用叉积】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct data{
	int x,y;
}a[1010];
int ans[1010],num;
int n;
bool p[1010];
inline int dis(data a,data b)
{
	int x=a.x-b.x,y=a.y-b.y;
	return (x*x+y*y);
}
inline int cj(data a,data b,data c)
{
	return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
int main()
{
	freopen("aneye.in","r",stdin);
	freopen("aneye.out","w",stdout);
	int i,j,k;
	scanf("%d",&n);
	num=1;
	for(i=1;i<=n;++i)
	 {
	 	scanf("%d%d",&a[i].x,&a[i].y);
	 	if(a[i].y<a[num].y) num=i;
	 	p[i]=0;
	 }
	p[num]=1; ans[1]=num;
	for(i=2;i<=n;++i)
	 {
	 	j=1;
	 	while(p[j]) ++j;
	 	k=j+1;
	 	while(k<=n)
	 	 {
	 	 	if(!p[k])
	 	     {
	 	     	int t=cj(a[k],a[j],a[ans[i-1]]);
	 	     	if(t>0||!t&&(dis(a[k],a[ans[i-1]])<dis(a[j],a[ans[i-1]])))
	 	     	  j=k;
			  }
			++k;
		  }
		p[j]=1; ans[i]=j;
	 }
	 printf("%d ",n);
	for(i=1;i<=n;++i) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}




posted @ 2016-08-27 17:04  lris0-0  阅读(423)  评论(0编辑  收藏  举报
过去的终会化为美满的财富~o( =∩ω∩= )m