HDU1392 Surround the Trees(凸包模版题)
来源:互联网 发布:初学者学化妆知乎 编辑:程序博客网 时间:2024/05/17 10:03
HDU1392 Surround the Trees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11173 Accepted Submission(s): 4337
Problem Description
There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can you help him?
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.
There are no more than 100 trees.
Input
The input contains one or more data sets. At first line of each input data set is number of trees in this data set, it is followed by series of coordinates of the trees. Each coordinate is a positive integer pair, and each integer is less than 32767. Each pair is separated by blank.
Zero at line for number of trees terminates the input for your program.
Zero at line for number of trees terminates the input for your program.
Output
The minimal length of the rope. The precision should be 10^-2.
Sample Input
9
12 7
24 9
30 5
41 9
80 7
50 87
22 9
45 1
50 7
0
Sample Ouput
243.06
题目大意
给你一个数n,代表一共有多少课树,然后给你n对点表示每棵树的坐标,要你求一个多边形能把所有的点包起来。
典型的凸包,Graham算法题,直接套模板就可以了。
要注意的是当树只有一棵或者两棵的情况,因为不会形成凸包,所以需要单独处理一下。
这个是一般计算几何里要用到的关于点和线的处理的模板,比较全
以下是关于点的
const double eps = 1e-8;const double PI = acos(-1.0);int sgn(double x){if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1;}struct Point{ double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } //点积 double operator *(const Point &b)const { return x*b.x + y*b.y; } //绕原点旋转角度B(弧度值),后x,y的变化 void transXY(double B) { double tx = x,ty = y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); }};关于线的
struct Line{ Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; }//两直线相交求交点//第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交//只有第一个值为2时,交点才有意义 pair<int,Point> operator &(const Line &b)const { Point res = s; if(sgn((s-e)^(b.s-b.e)) == 0) { if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);//重合 else return make_pair(1,res);//平行 } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); }};求两点距离的
double dist(Point a,Point b){ return sqrt((a-b)*(a-b));}接下来这个就是Graham算法题的模版
点的编号0~n-1,存在list[MAXN]里
返回凸包结果Stack[0~top-1]
返回凸包结果Stack[0~top-1]
Stack[]里就是按顺序存的凸包的点在list[]的序号
void Graham(int n){ Point p0; int k = 0; p0 = list[0]; //找最下边的一个点 for(int i = 1;i < n;i++) { if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) ) { p0 = list[i]; k = i; } } swap(list[k],list[0]); sort(list+1,list+n,_cmp); if(n == 1) { top = 1; Stack[0] = 0; return; } if(n == 2) { top = 2; Stack[0] = 0; Stack[1] = 1; return ; } Stack[0] = 0; Stack[1] = 1; top = 2; for(int i = 2;i < n;i++) { while(top > 1 &&sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <=0) top--; Stack[top++] = i; }}
以下是全部代码
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);int sgn(double x){if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1;}struct Point{ double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } //点积 double operator *(const Point &b)const { return x*b.x + y*b.y; } //绕原点旋转角度B(弧度值),后x,y的变化 void transXY(double B) { double tx = x,ty = y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); }};struct Line{ Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; }//两直线相交求交点//第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交//只有第一个值为2时,交点才有意义 pair<int,Point> operator &(const Line &b)const { Point res = s; if(sgn((s-e)^(b.s-b.e)) == 0) { if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);//重合 else return make_pair(1,res);//平行 } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); }};double dist(Point a,Point b){ return sqrt((a-b)*(a-b));}const int MAXN = 1010;Point list[MAXN];int Stack[MAXN],top;//相对于list[0]的极角排序bool _cmp(Point p1,Point p2){ double tmp = (p1-list[0])^(p2-list[0]); if(sgn(tmp) > 0)return true; else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0) return true; else return false;}void Graham(int n){ Point p0; int k = 0; p0 = list[0]; //找最下边的一个点 for(int i = 1;i < n;i++) { if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) ) { p0 = list[i]; k = i; } } swap(list[k],list[0]); sort(list+1,list+n,_cmp); if(n == 1) { top = 1; Stack[0] = 0; return; } if(n == 2) { top = 2; Stack[0] = 0; Stack[1] = 1; return ; } Stack[0] = 0; Stack[1] = 1; top = 2; for(int i = 2;i < n;i++) { while(top > 1 &&sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <=0) top--; Stack[top++] = i; }}int main(){int n;while(scanf("%d",&n)&&n){for(int i=0;i<n;i++){scanf("%lf%lf",&list[i].x,&list[i].y);}double ans;//当树只有一棵时,就为0 if(n==1){ans=0.0; printf("%.2lf\n",ans);continue;}//当树只有两棵时,不会形成凸包,直接求两点距离就好了 if(n==2){ans=dist(list[0],list[1]);printf("%.2lf\n",ans);continue;}Graham(n);//这就是套用模版直接求出凸包//求出凸包后,求凸包的周长 ans=dist(list[Stack[top-1]],list[Stack[0]]);for(int i=0;i<top-1;i++){ans+=dist(list[Stack[i]],list[Stack[i+1]]);}printf("%.2lf\n",ans);}return 0;}
模版里有很多子函数其实并没有用到,但是函数很全,一般做计算几何的题目,用这些模板足够了。
题目网址:HDU1392 Surround the Trees
阅读全文
1 0
- HDU1392 Surround the Trees(凸包模版题)
- 凸包模版 HDU1392 Surround the Trees
- HDU1392--Surround the Trees--凸包
- 凸包问题 hdu1392 Surround the Trees
- HDU1392 Surround the Trees 简单凸包
- 【凸包】HDU1392 Surround the Trees
- HDU1392 Surround the Trees(凸包)
- hdu1392 Surround the Trees 凸包
- hdu1392(Surround the Trees)凸包问题
- HDU1392:Surround the Trees(凸包问题)
- POJ1113(Wall) && Hdu1392(Surround the Trees) (计算几何--凸包)
- hdu1392-Surround the Trees
- HDOJ_1392 Surround The Trees (凸包模版)
- hdu1392-Surround the Trees 求凸包
- 【计算几何初步-凸包-Jarvis步进法。】【HDU1392】Surround the Trees
- hdu 1392 Surround the Trees(凸包模版)
- Surround the Trees&&凸包入门题
- Surround the Trees(凸包)
- 密码学
- return false,preventDefault,stopPropagation的用法对比
- 什么是 秘钥延伸(Key Stretching)
- Python迭代器与生成器
- AJAX实现分页及动态增删操作
- HDU1392 Surround the Trees(凸包模版题)
- CSS权重计算问题
- python数据分析学习路线
- jmeter 保存响应到文件
- Android学习迷茫问下自己14个问题
- nginx源码学习2——扒、封装红黑树代码
- Redis主从复制和集群配置
- 深入浅出JMS(一)--JMS基本概念
- 用ajax向table插一条一条数据,使插入最新数据都在第一行