閱讀816 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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


最後更新:2017-04-04 07:03:57

  上一篇:go 開源社區自己從來不想承認的九大事實
  下一篇:go 智能手機廠商切莫陷入“核大戰”