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;
}


目录
相关文章
|
4月前
|
JavaScript
【leetcode】221. 最大正方形 动态规划法
【leetcode】221. 最大正方形 动态规划法
21 0
|
4月前
|
算法 程序员 索引
【算法训练-动态规划 四】【二维DP问题】最大正方形、最小路径和、不同路径
【算法训练-动态规划 四】【二维DP问题】最大正方形、最小路径和、不同路径
86 0
|
算法 容器
587. 安装栅栏 : 二维凸包模板题
587. 安装栅栏 : 二维凸包模板题
poj 2642 The Brick Stops Here(二维0/1背包)
点击打开链接poj 2642 思路: 0/1背包 分析: 1 题目给定n个物品,并且每个物品只有两种的选择很明显就是0/1背包的特性。 2 题目给定c个客户的要求,每一个客户都要求最后金子的平均浓度在min~max这个区间,并且每个客户要...
1085 0
[LintCode] 最多有多少个点在一条直线上
1 /** 2 * Definition for a point. 3 * struct Point { 4 * int x; 5 * int y; 6 * Point() : x(0), y(0) {} 7 * Point(...
924 0
|
机器学习/深度学习
|
机器学习/深度学习