2015年ALPC暑期专题练习I (计算几何) Space Ant


开始用求凸包的方法做的代码。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<map>
#include<set>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
using namespace std;
/*********************************************************************/
const int MAX_NUM = 50+10;
struct plant{
  int id,x,y;
  double cos;
}p[MAX_NUM];
int sk[MAX_NUM],skLen;

double GetCosWithX (plant& a, plant& b){return (b.x-a.x) / sqrt( pow(a.x-b.x,2)+pow(a.y-b.y,2) );}
double min_2 (int x,int y) {return x<y?x:y;}
int CrossMuti (plant a,plant b){return a.x*b.y-a.y*b.x;}
bool cmpPlant (plant a,plant b){
  if (a.cos>b.cos)
	return true;
  else if (a.cos==b.cos)
	return a.x<=b.x&&a.y<=b.y;
  else
	return false;
}
void HandleStack (int i)
{
  if (skLen<=3){
	sk[skLen++]=i;
	return;
  }
  plant ab,bc;
  while (1)
  {
	if (skLen<2){printf ("handle error\n");return;}
	ab.x=p[sk[skLen-1]].x-p[sk[skLen-2]].x;
	ab.y=p[sk[skLen-1]].y-p[sk[skLen-2]].y;
	bc.x=p[i].x-p[sk[skLen-1]].x;
	bc.y=p[i].y-p[sk[skLen-1]].y;
	if (CrossMuti(ab,bc)>=0){
	  sk[skLen++]=i;
	  return;
	}
	else
	  --skLen;
  }
}
/*********************************************************************/
int main()
{
  int t,n;
  scanf ("%d",&t);
  while (t--)
  {
	scanf ("%d",&n);
	int minY=1000,minX=1000,minID;
	//set<point,int>
	for (int i=0;i<n;i++){
	  scanf ("%d%d%d",&p[i].id,&p[i].x,&p[i].y);
	  if (minY>p[i].y){
		minY=p[i].y;
		minX=p[i].x;
		minID=i;
	  }
	  else if (minY==p[i].y && minX>p[i].x){
		minX=p[i].x;
		minID=i;
	  }
	}
	p[minID].cos=1.0;
	for (int i=0;i<n;i++){
	  if (i==minID) continue;
	  p[i].cos=GetCosWithX (p[minID],p[i]);
	}
	sort (p,p+n,cmpPlant);
	/*for (int i=0;i<n;i++)
	  printf ("%d ",p[i].id);
	printf ("\n");*/
	skLen=0;
	sk[skLen++]=0;
	for (int i=1;i<n;i++){
	  HandleStack (i);
	  /*for (int j=0;j<skLen;j++)
		printf ("%d ",p[sk[j]].id);
		printf ("\n");*/
	}
	for (int j=0;j<skLen;j++)
	  printf ("%d ",p[sk[j]].id);
	printf ("\n");
  }
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值