Surround the Trees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6231 Accepted Submission(s): 2339
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.
Zero at line for number of trees terminates the input for your program.
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
/***這是一個求凸包的模板***/
using namespace std;
const int MAXN = 100;
const double eps = 1e-8;
struct Point
{
int x;
int y;
};
struct Point p[MAXN]; // 保存輸入結點
struct Point st[MAXN]; // 保存凸包結點,把que當一個棧來使用
int top; // 記錄棧頂位置
double dis(Point a, Point b)// 求a, b兩點距離
{
return sqrt(double((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)));
}
int cross(Point p1,Point p2, Point p0)// 求P0P1與P0P2的叉積
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool cmp(Point p1,Point p2)
{
int k = cross(p2,p1,p[0]); //p0p2叉乘p0p1
if(k<0||(!k&&dis(p1,p[0])-dis(p2,p[0])>eps))//p1的極角比p2小或者極角相等去距離大的
return true;
else return false;
}
void GrahamScan(int n)
{
Point tmp;
int k = 0;
for(int i=1; i<n; ++i)//找出y值(y值相同時找x最小)最小的點作爲起始點P0
if((p[i].y < p[k].y) || ((p[i].y==p[k].y) && (p[i].x<p[k].x)))
k = i;
tmp = p[0];
p[0] = p[k];
p[k] = tmp;
sort(p+1,p+n,cmp);// 按極角大小排序
top = -1;
st[++top] = p[0];
st[++top] = p[1];
st[++top] = p[2]; //先把極角最小的0, 1, 2三點存入棧中
for(int i=3; i<n; ++i) //從第3點開始,直到最後,如果不能左轉,則退棧.
{
while((cross(p[i], st[top],st[top-1]))>=0) //如果不能左轉,則退棧
top--;
st[++top]=p[i];
}
++top;
}
/***********************************************/
int main()
{
int n,i;
double s_dist;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
else
{
for(i=0; i<n; i++)
scanf("%d%d",&p[i].x,&p[i].y);
if(n==1)//如果只有一個點
printf("0\n");
else if (n==2)//如果有兩個點
printf("%.2lf\n",dis(p[0],p[1]));
else
{
GrahamScan(n);
s_dist=dis(st[0],st[top-1]);
for(i=0; i<top-1; i++)
s_dist=s_dist+dis(st[i],st[i+1]);
printf("%.2lf\n",s_dist);
}
}
}
return 0;
}