1. 程式人生 > >POJ 1113 Wall 凸包 裸

POJ 1113 Wall 凸包 裸

nbsp blank 2.0 sin all str fin href com

LINK

題意:給出一個簡單幾何,問與其邊距離長為L的幾何圖形的周長。

思路:求一個幾何圖形的最小外接幾何,就是求凸包,距離為L相當於再多增加上一個圓的周長(因為只有四個角)。看了黑書使用graham算法極角序求凸包會有點小問題,最好用水平序比較好。或者用Melkman算法

/** @Date    : 2017-07-13 14:17:05
  * @FileName: POJ 1113 極角序求凸包 基礎凸包.cpp
  * @Platform: Windows
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#include <math.h>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
const double Pi = acos(-1.0);
struct point
{
	int x, y;
	point(){}
	point(int _x, int _y){x = _x, y = _y;}
	point operator -(const point &b) const
	{
		return point(x - b.x, y - b.y);
	}
	int operator *(const point &b) const 
	{
		return x * b.x + y * b.y;
	}
	int operator ^(const point &b) const
	{
		return x * b.y - y * b.x;
	}
};

double xmult(point p1, point p2, point p0)  
{  
    return (p1 - p0) ^ (p2 - p0);  
}  

double distc(point a, point b)
{
	return sqrt((double)((b - a) * (b - a)));
}

int n, l;
point p[N];
stack<int>s;

int cmp(point a, point b)//以p[0]基準 極角序排序
{
	int t = xmult(a, b, p[0]);
	if(t > 0)
		return 1;
	if(t == 0)
		return distc(a, p[0]) < distc(b, p[0]);
	if(t < 0)
		return 0;
}

void graham()
{
	while(!s.empty())
		s.pop();
	for(int i = 0; i < min(n, 2); i++)
		s.push(i);
	int t = 1;
	for(int i = 2; i < n; i++)
	{
		while(s.size() > 1)
		{
			int p2 = s.top();
			s.pop();
			int p1 = s.top();
			if(xmult(p[p1], p[p2], p[i]) > 0)
			{
				s.push(p2);
				break;
			} 
		}
		s.push(i);
	}

}

int main()
{
	while(~scanf("%d%d", &n, &l))
	{
		int x, y;
		int mix, miy;
		mix = miy = INF;
		int pos = -1;
		for(int i = 0; i < n; i++)
		{
			scanf("%d%d", &x, &y);
			p[i] = point(x, y);
			if(miy > y || miy == y && mix > x)//註意選第一個點 是最左下方的
			{
				mix = x, miy = y;
				pos = i;
			}
		}
		swap(p[pos], p[0]);
		sort(p + 1, p + n, cmp);
		graham();
		double ans = l * Pi * 2.0000;
		int t = 0;
		while(!s.empty())
		{
			ans += distc(p[t], p[s.top()]);
			t = s.top();
			s.pop();
		}
		printf("%d\n", (int)(ans + 0.500000));
	}
    return 0;
}

POJ 1113 Wall 凸包 裸