POJ 1113 二维凸包

简介:

题意:国王把自己城堡看成了一个点,让你找一个凸包把所有的城堡包住并且这个凸包距离城堡最近不能小于L,求这个凸包的最短长度。

题意就是求凸包最短长度再加上以L为半径的圆的周长就有解了。是一道使用Graham扫描法的模板题。一开始我用STL里的stack建栈,c++超时,g++985ms,而且感觉不是那么方便。之后我又用数组建栈写了,果断0ms,并且代码也没有那么长。

这个数组建栈的

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double PointType;
struct point
{
    PointType x,y;
};
point data[1005],stack[1005],MinA;
int top;
PointType Direction(point pi,point pj,point pk) //判断向量PiPj在向量PiPk的顺逆时针方向 +顺-逆0共线
{
    return (pj.x-pi.x)*(pk.y-pi.y)-(pk.x-pi.x)*(pj.y-pi.y);
}
PointType Dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)
{
    PointType k=Direction(MinA,a,b);
    if(k>0) return 1;
    if(k<0) return 0;
    return Dis(MinA,a)>Dis(MinA,b);
}
void Graham_Scan(point *a,int numa)
{
    for(int i=0; i<numa; i++)
        if(a[i].y<a[0].y||(a[i].y==a[0].y&&a[i].x<a[0].x))
            swap(a[i],a[0]);
    MinA=a[0],top=0;
    sort(a+1,a+numa,cmp);
    stack[top++]=a[0],stack[top++]=a[1],stack[top++]=a[2];
    for(int i=3; i<numa; i++)
    {
        while(Direction(stack[top-2],stack[top-1],a[i])<0)
            top--;
        stack[top++]=a[i];
    }
}
int main()
{
    int n;
    double r,pi=3.141592654;
    while(~scanf("%d%lf",&n,&r))
    {
        double sum=0;
        for(int i=0; i<n; i++)
            scanf("%lf%lf",&data[i].x,&data[i].y);
        Graham_Scan(data,n);
        for(int i=1; i<top; i++)
            sum+=Dis(stack[i],stack[i-1]);
        sum+=Dis(stack[0],stack[top-1]);
        sum+=pi*r*2;
        printf("%.0f\n",sum);
    }
    return 0;
}

这个是用STL的stack栈写的。。

#include <iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double PointType;
struct point
{
    PointType x,y;
    int num;
};
point MinA;
point Next_To_Point(stack<point> temp)
{
    point first,second;
    first=temp.top();
    temp.pop();
    second=temp.top();
    temp.push(first);
    return second;
}
PointType Direction(point pi,point pj,point pk) //判断向量PiPj在向量PiPk的顺逆时针方向 +顺-逆0共线
{
    return (pj.x-pi.x)*(pk.y-pi.y)-(pk.x-pi.x)*(pj.y-pi.y);
}
PointType Dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)
{
    PointType k=Direction(MinA,a,b);
    if(k>0) return 1;
    if(k<0) return 0;
    return Dis(MinA,a)>Dis(MinA,b);
}
stack<point> Graham_Scan(point *a,int numa)
{
    stack<point> s;
    for(int i=0; i<numa; i++)
        if(a[i].y<a[0].y||(a[i].y==a[0].y&&a[i].x<a[0].x))
            swap(a[i],a[0]);
    MinA=a[0];
    sort(a+1,a+numa,cmp);
    s.push(a[0]),s.push(a[1]),s.push(a[2]);
    for(int i=3; i<numa; i++)
    {
        while(Direction(Next_To_Point(s),s.top(),a[i])<0&&!s.empty())
            s.pop();
        s.push(a[i]);
    }
    return s;
}
point data[1005],st[1005];
int main()
{
    int n;double r,pi=3.141592654;stack<point> ans;
    while(~scanf("%d%lf",&n,&r))
    {
        double sum=0;int w=0;
        for(int i=0;i<n;i++)
        scanf("%lf%lf",&data[i].x,&data[i].y);
        ans=Graham_Scan(data,n);
        while(!ans.empty())
            st[w++]=ans.top(),ans.pop();
        for(int i=1;i<w;i++)
            sum+=Dis(st[i],st[i-1]);
        sum+=Dis(st[0],st[w-1]);
        sum+=pi*r*2;
        printf("%.0f\n",sum);
    }
    return 0;
}


目录
相关文章
|
Python
LeetCode每日一题——883. 三维形体投影面积
在 n x n 的网格 grid 中,我们放置了一些与 x,y,z 三轴对齐的 1 x 1 x 1 立方体。
95 0
LeetCode每日一题——883. 三维形体投影面积
|
算法 容器
587. 安装栅栏 : 二维凸包模板题
587. 安装栅栏 : 二维凸包模板题
|
机器学习/深度学习 人工智能
|
算法 Windows 小程序
[LintCode] 最多有多少个点在一条直线上
1 /** 2 * Definition for a point. 3 * struct Point { 4 * int x; 5 * int y; 6 * Point() : x(0), y(0) {} 7 * Point(...
903 0
|
算法
计算几何 : 凸包学习笔记 --- Graham 扫描法
凸包 (只针对二维平面内的凸包) 一、定义 简单的说,在一个二维平面内有n个点的集合S,现在要你选择一个点集C,C中的点构成一个凸多边形G,使得S集合的所有点要么在G内,要么在G上,并且保证这个凸多边形的面积最小,我们要求的就是这个C集合。
1775 0
|
机器学习/深度学习

热门文章

最新文章