Surround the Trees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7987 Accepted Submission(s): 3044
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.
代碼:
直接套用Graham算法模板即可,注意特殊考慮輸入點爲1和2的情況,wa了一次。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
struct Point{
double x, y;
};
const int MAXN = 200;
Point list[MAXN];
int stack[MAXN], top;
double crossProduct(Point a, Point b){
return a.x*b.y - a.y*b.x;
}
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
else return 1;
}
Point sub(Point a, Point b){
Point p;
p.x = a.x - b.x;
p.y = a.y - b.y;
return p;
}
double dist(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
//相對於極點list[0]的極角排序
bool cmp(Point p1, Point p2){
double temp = crossProduct(sub(p1, list[0]), sub(p2, list[0]));
if(sgn(temp)>0) return true;
else if(sgn(temp)==0 && sgn(dist(p1, list[0])-dist(p2, list[0]))<=0) return true;
else return false;
}
/*
* 求凸包,Graham算法
* 點的編號0~n-1
* 返回凸包結果Stack[0~top-1]爲凸包的編號
*/
void Graham(int n){
Point p0 = list[0];
int k = 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);
stack[0] = 0;
if(n==1){top = 1; return;}
stack[1] = 1;
if(n==2){top = 2; return;}
top = 2;
for(int i=2;i<n;i++){
while(top>1 && sgn(crossProduct(sub(list[stack[top-1]], list[stack[top-2]]), sub(list[i], list[stack[top-2]])))<=0){
top--;
}
stack[top++] = i;
}
}
int main(){
int n;
while(1){
scanf("%d", &n);
if(n == 0) break;
for(int i=0;i<n;i++){
scanf("%lf %lf", &list[i].x, &list[i].y);
}
if(n==1){
printf("0.00\n");
continue;
}
if(n==2){
printf("%.2lf\n", dist(list[0],list[1]));
continue;
}
Graham(n);
double ans = 0;
for(int i=0;i<top-1;i++)
ans += dist(list[stack[i]], list[stack[i+1]]);
ans += dist(list[stack[0]], list[stack[top-1]]);
printf("%.2lf\n", ans);
}
return 0;
}