凸包周长(codevs 1298)
Description
给出平面上n个点,求出这n个点形成的凸包的周长。凸包的定义:能覆盖住这个n个点的最小凸多边形。
Input Description
第一行一个整数n,接下来n行,每行两个整数x和y,表示一个点的坐标。
数据范围 1 <= n <= 100000
-10000<=x,y<=10000
Output Description
一行一个实数,表示凸包周长,保留一位小数.
Sample Input
5
0 0
2 2
0 2
2 0
1 1
Sample Output
8.0
题解:
模板题
关于凸包算法:
http://www.cnblogs.com/Booble/archive/2011/02/28/1967179.html
http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html#2065991
这里直接粘代码(采用Graham算法,极角序):
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define pi acos(-1.0)
#define maxn (1000000 + 50)
#define mod 1000000007
#define INF 1e20
#define Lowbit(x) (x & (-x))
using namespace std;
typedef long long int LLI;
struct Point {
double x;
double y;
Point() {}
Point(double xx,double yy) {
x = xx,y = yy;
}
Point operator-(const Point &b)const {
return Point(x - b.x,y - b.y);
}
double operator*(const Point &b)const {
return x * b.x + y * b.y;
}
double operator^(const Point &b)const {
return x * b.y - y * b.x;
}
} List[maxn];
int aStack[maxn],top;
double Xmult(Point p0,Point p1,Point p2) {
return (p1 - p0) ^ (p2 - p0);
}
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(Point p1,Point p2) {
double temp = Xmult(List[0],p1,p2);
if(temp > 0) return true;
if(temp == 0 && Dis(List[0],p1) < Dis(List[0],p2)) return true;
return false;
}
void Init(int n) {
if(n == 0) return;
scanf("%lf%lf",&List[0].x,&List[0].y);
Point p0(List[0].x,List[0].y);
int k = 0;
for(int i = 1; i < n; i ++) {
scanf("%lf%lf",&List[i].x,&List[i].y);
if(p0.y > List[i].y || (p0.y == List[i].y && p0.x > List[i].x)) {
p0 = Point(List[i].x,List[i].y);
k = i;
}
}
List[k] = List[0];
List[0] = p0;
sort(List + 1,List + n,cmp);
}
void Graham(int n) {
if(n == 1) {
aStack[0] = 0;
top = 0;
return;
}
top = 1;
aStack[0] = 0;
aStack[1] = 1;
if(n == 2) return;
for(int i = 2; i < n; i ++) {
while(top > 0 && Xmult(List[aStack[top - 1]],List[aStack[top]],List[i]) <= 0)
top --;
top ++;
aStack[top] = i;
}
}
int main() {
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n;
scanf("%d",&n);
Init(n);
Graham(n);
double sum = Dis(List[aStack[0]],List[aStack[top]]);
for(int i = 1;i <= top;i ++){
sum = sum + Dis(List[aStack[i - 1]],List[aStack[i]]);
}
printf("%.1lf\n",sum);
return 0;
}