poj 1681 极角排序(只能向左拐的虫子)

题意:有个虫子只能向左拐,给定平面上若干点,问这个虫子最多能到达多少个点,并依次输出经过的点。

思路:一开始的思路是做多次graham,每次最后一个点不取回出发点,但是一直会wa。

所以只能用极角排序,时间复杂度O(n*n*lgn)。

#include <stdio.h>
#include <string.h>
#include <math.h>
#define N 55
struct node{
	int id,x,y;
}p[N],res[N];
int n,re,T,top;
double dis(struct node a,struct node b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int multi(struct node a,struct node b,struct node c){
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int cmp(const struct node *a,const struct node *b){
	int temp = multi(res[top],*a,*b);
	if(temp != 0)//如果极角分出大小;注意排序的顺序
		return -temp;
	return dis(res[top],*a)-dis(res[top],*b);//否则先找离其实点近的
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		int i,miny;
		top = -1;
		scanf("%d",&n);
		for(i = miny = 0;i<n;i++){
			scanf("%d %d %d",&p[i].id,&p[i].x,&p[i].y);
			if(p[i].y < p[miny].y)
				miny = i;
		}
		if(miny){//寻找y坐标最小的点当作初始点
			struct node temp = p[0];
			p[0] = p[miny];
			p[miny] = temp;
		}
		printf("%d ",n);
		res[++top] = p[0];
		for(i = 1;i<n-1;i++){//依次对剩下的点进行极角排序
			qsort(p+i,n-i,sizeof(struct node),cmp);
			res[++top] = p[i];//站在初始点来看,选出的是最右侧的点
		}
		res[++top] = p[n-1];
		for(i = 0;i<=top;i++)
			printf("%d ",res[i].id);
		putchar('\n');
	}
	return 0;
}

graham代码会有几组数据挂掉(discuss里有个人提供了很多数据):

#include <stdio.h>
#include <string.h>
#define N 55
struct node{
	int id,x,y;
}p[N],s[N];
int n,re,T;
int cmp(const struct node *a,const struct node *b){
	if((*a).y == (*b).y)
		return (*a).x - (*b).x;
	return (*a).y - (*b).y;
}
int multi(struct node a,struct node b,struct node c){
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int graham(){
	int i,j,k,m;
	for(i = m = 0;i<n;i++){
		while(m>1 && multi(s[m-2],s[m-1],p[i])<=0)
			m--;
		s[m++] = p[i];
	}
	k = m;
	if(n>m)
	for(i = n-2;i>0;i--){
		while(m>k && multi(s[m-2],s[m-1],p[i])<=0)
			m--;
		s[m++] = p[i];
	}
	for(i = 0;i<m;i++)
		printf("%d ",s[i].id);
	for(i = k = 0;i<n;i++){
		for(j = 0;j<m;j++)
			if(p[i].x==s[j].x && p[i].y==s[j].y)
				break;
		if(j == m)
			p[k++] = p[i];
	}
	n = k;
	return m;
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		int i,k;
		scanf("%d",&n);
		for(i = 0;i<n;i++)
			scanf("%d %d %d",&p[i].id,&p[i].x,&p[i].y);
		printf("%d ",re = n);
		qsort(p,n,sizeof(struct node),cmp);
		while(1){
			graham();
			if(n <= 1){
				if(n == 1)
					printf("%d",p[0].id);
				break;			
			}		
		}
		putchar('\n');
	}
	return 0;
}


你可能感兴趣的:(poj 1681 极角排序(只能向左拐的虫子))