极角排序 POJ1696
来源:互联网 发布:里诺仓库管理软件sql 编辑:程序博客网 时间:2024/05/21 15:48
VJ题目连接
题目大意
一种奇怪的虫子不能右转且走过路线之间不能有交点,吃植物才能存活,给出植物的坐标,求虫子要怎样走才能活得最久(吃的植物越多活越久)
输入:样例数,n组样例,每组给出一个n,然后n行每行给出3个数,分别是植物编号、植物x坐标、植物y坐标
输出:能吃的最大植物数目,并给出路线
解体思路
因为虫子只能左转且路线不能有交点,很容易想到让虫子逆时针螺旋地去吃植物,由外到内,可以将所有植物吃完。因为逆时针路线一定是左转,螺旋线保证不相交,从最外到最内是肯定可以吃完所有植物的。
怎样构造这样的螺旋线呢?这要用极角排序。从最下方的点开始,将这个点作为基点,对其他所有点进行极角排序,然后取极角最小点,重新设立为基点,对剩余点重新排序,依次类推直至剩最后一个点。
为什么要从最下点开始?因为这样可以保证其他点都在上方,这样就可以使其他点与该点的极角都>=0,这样可以以x轴正方向为基线找出夹角最小的点。之后由找到的新点为基点,可以保证其他未选择的点都在上一个点与新基点连线的一侧,这样就可以以这条连线作为基线求最小极角。
怎样求对极角进行排序?简单的做法是用sort函数,然后自定义一个cmp比较函数,大致如下:
//极角排序规则 bool cmp(const Point &p1, const Point &p2) { double tmp; tmp=multiply(p1,p2,PointSet[cnt]); //外积大于0 if(tmp>0) { return true; } //两线重合时选择距离更小的 else if(fabs(tmp)<=eps && dis(PointSet[cnt],p1)<dis(PointSet[cnt],p2)) { return true; } return false; }
这里没有直接求角度,而是利用外积来判断,外积函数如下:
//小于0,说明向量p0p1的极角大于p0p2的极角double multiply(Point p1,Point p2,Point p0){ return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));}
显然,若p1p0与p2p0的外积>0,则p1在p2右侧(若以上述的基线为水平线),相反,若外积<0,则p1在p2左侧,而我们要的极角最小的点即在最右侧的点。若外积为0,则三点共线,我们需要优先选择更靠近基点的点。
AC代码
#include <iostream>#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define eps 0.00000001using namespace std;struct Point{ double x,y,num;};const int maxN=55;Point PointSet[maxN]; //输入的点集 Point ans[maxN]; //输出的点集 int n; //点的个数 int cnt; //当前判断基点 //小于0,说明向量p0p1的极角大于p0p2的极角double multiply(Point p1,Point p2,Point p0){ return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));}//p1p2距离 double dis(Point p1,Point p2){ return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));}//极角排序规则 bool cmp(const Point &p1, const Point &p2) { double tmp; tmp=multiply(p1,p2,PointSet[cnt]); //外积大于0 if(tmp>0) { return true; } //两线重合时选择距离更小的 else if(fabs(tmp)<=eps && dis(PointSet[cnt],p1)<dis(PointSet[cnt],p2)) { return true; } return false; } int main(){ int cas; scanf("%d",&cas); while(cas--) { scanf("%d",&n); memset(PointSet,0,sizeof PointSet); int i; for(i=0;i<n;i++) { scanf("%d%lf%lf",&PointSet[i].num,&PointSet[i].x,&PointSet[i].y); //找出最下点 if(PointSet[i].y<PointSet[0].y) { Point tmp=PointSet[0]; PointSet[0]=PointSet[i]; PointSet[i]=tmp; } } //初始基点 cnt=0; //排序 sort(PointSet+1,PointSet+n,cmp); ans[cnt]=PointSet[cnt++]; for(i=2;i<n;i++) { //依次设立基点排序 sort(PointSet+cnt,PointSet+n,cmp); ans[cnt]=PointSet[cnt++]; } ans[cnt]=PointSet[cnt++]; printf("%d",cnt); for(i=0;i<cnt;i++) { printf(" %d",ans[i].num); } printf("\n"); } return 0;}
0 0
- 极角排序 POJ1696
- Poj1696计算几何的叉积+极角排序+贪心
- 二维坐标系极角排序的应用(POJ1696)
- POJ1696---Space Ant(基础计算几何:极角排序)
- POJ1696 space ant(计算几何,极角排序)
- poj1696 Space Ant (极角排序,叉积)
- poj1696
- poj1696
- poj1696
- poj1696---计算几何
- poj1696 ,第一次用泛型
- POJ1696-凸包
- POJ1696-Space Ant
- poj1696 Space Ant
- POJ1696-Space Ant
- Poj1696 Space Ant
- poj1696 凸包
- poj1696 Space Ant
- mac下Android Studio常用的一些快捷键
- P3250 最长链
- java ArrayList与LinkedList 使用for,forearch,Iterator的遍历效率
- iOS程序启动与运转
- 如何使用ProgressDialog
- 极角排序 POJ1696
- 好的架构师,挖空心思偷懒
- 气泡样式提示框
- iOS开发之自定义表情键盘(组件封装与自动布局)
- Error:Failed to create directory 'C:\Users\Administrator\.gradle\caches\2.8\scripts\ijinit7_5jx13p26
- UI基础第二天(代码)
- js 字符串截取(包含中英文)
- 如何捕获java线程中的逃逸的异常
- sublime text