凸包

来源:互联网 发布:mac系统能玩lol吗 编辑:程序博客网 时间:2024/06/05 08:04
凸包凸包
 
A - Surround the Trees
Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u
SubmitStatus

Description

There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can you help him?
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.

凸包


There are no more than 100 trees.
 

Input

The input contains one or more data sets. At first line of each input data set is number of trees in this data set, it is followed by series of coordinates of the trees. Each coordinate is a positive integer pair, and each integer is less than 32767. Each pair is separated by blank.

Zero at line for number of trees terminates the input for your program.
 

Output

The minimal length of the rope. The precision should be 10^-2.
 

Sample Input

9 12 7 24 9 30 5 41 9 80 7 50 87 22 9 45 1 50 7 0
 

Sample Output

243.06
 MicrosoftInternetExplorer402DocumentNotSpecified7.8Normal0

A题(Graphm求凸包)

实际上就是求一个凸包,不过要注意,n=2的时候,不要将总长度乘以2

 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

 

using namespace std;

 

struct point {

    double x, y;

pnt[105];

 

int n;

point res[105];

 

bool mult(point sp, point ep, point op) {

    return(sp.x-op.x)*(ep.y-op.y) >= (ep.x-op.x)*(sp.y-op.y);

}

 

bool operator (const point &l, const point &r) {

    return l.y

}

 

double graham() {

    int i, len, top 1;

    sort(pnt, pnt n);

    if(n == 0)

        return 0;

    res[0] pnt[0];

    if(n == 1) return 0;

    res[1] pnt[1];

    if(n == 2)

        return sqrt((res[1].x-res[0].x)*(res[1].x-res[0].x)+(res[1].y-res[0].y)*(res[1].y-res[0].y));

    res[2] pnt[2];

    for(i=2; i

        while(top && mult(pnt[i], res[top], res[top-1]))

            top--;

        res[++top] pnt[i];

    }

    len top;

    res[++top] pnt[n-2];

    for(i=n-3; i>=0; i--) {

        while (top!=len && mult(pnt[i], res[top], res[top-1]))

            top--;

        res[++top] pnt[i];

    }

    double sum 0;

    for (int i=1; i<=top; i++) {

        sum += sqrt((res[i].x-res[i-1].x)*(res[i].x-res[i-1].x) (res[i].y-res[i-1].y)*(res[i].y-res[i-1].y));

    }

    return sum;

}

 

int main()

{

    while (scanf("%d", &n) != EOF) {

        if (n == 0) break;

        for (int i=0; i

            scanf("%lf %lf", &pnt[i].x, &pnt[i].y);

        printf("%.2lf\n", graham());

    }

    return 0;

}

Graham's Scan法 求解凸包问题。

我写的是按照逆时针扫描,其中叉乘函数返回的是凸包的结果。凸包的结果保存在栈S[0...top]中。

PS:
1、求凸包时,必须确定至少有3个点。
2、一般把极点 S[0] 在最后 S[top+1] 处复制一份,便于计算。
3、初始化放2个点即可,3个点可能有bug(考虑开始三个点即 P[0]、P[1]、P[2] 共线的情况)。
4、排序时,对于极角相同的点,把距离小的排在前面比较好。这样求凸包时,可以把共线的点全部删掉,只保留距离最大的那个点。
      否则,求凸包时,程序会把这些共线的点全部加入凸包,使凸包上的点增加。(小优化)

[cpp] view plaincopy
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. using namespace std;  
  6.   
  7. #define 1005  
  8.   
  9. struct Point  
  10.  
  11.     int x,y;  
  12. }P[N],S[N];  
  13.   
  14. int n,top;  
  15.   
  16. double Dis(const Point& p1,const Point& p2)  
  17.  
  18.     return sqrt( (p1.x-p2.x)*(p1.x-p2.x) (p1.y-p2.y)*(p1.y-p2.y)*1.0 );  
  19.  
  20.   
  21. double Cross(const Point& p1,const Point& p2,const Point& p3,const Point& p4)  
  22.  
  23.     return (p2.x-p1.x)*(p4.y-p3.y) (p2.y-p1.y)*(p4.x-p3.x);  
  24.  
  25.   
  26. bool cmp(const Point& p1,const Point& p2)  
  27.  
  28.     double Cross(P[0],p1,P[0],p2);  
  29.     return C>0 Dis(P[0],p1)
  30.  
  31.   
  32. void Pole_Point()  
  33.  
  34.     int id;  
  35.     Point pp P[id=0];  
  36.     for(int i=1;i
  37.         if(P[i].y pp.y || P[i].y == pp.y && P[i].x pp.x)  
  38.             pp P[i] id i;  
  39.     P[id] P[0] P[0] pp;  
  40.  
  41.   
  42. void Convex_Hull()  
  43.  
  44.     Pole_Point();  
  45.     sort(P+1,P+n,cmp);  
  46.     S[0]=P[0],S[top=1]=P[1];  
  47.     for(int i=2;i
  48.      
  49.         while(top && Cross(S[top-1],S[top],S[top],P[i]) <= 0)  
  50.             --top;  
  51.         S[++top] P[i];  
  52.      
  53.  
  54.   
  55. int main()  
  56.  
  57.     while(~scanf("%d",&n))  
  58.      
  59.         for(int i=0;i
  60.             scanf("%d%d",&P[i].x,&P[i].y);  
  61.         Convex_Hull();  
  62.         for(int i=0;i<=top;i++)  
  63.             printf("%d %d\n",S[i].x,S[i].y);  
  64.      
  65.     return 0;  
  66.   
凸包模板
//凸包structpoint{ double x, y;};
 
bool
mult(point sp, pointep, point op)
{
return(sp.x- op.x) *(ep.y- op.y) >=(ep.x- op.x) *(sp.y- op.y);}
 
bool
operator<</FONT> (const point&l,const point&r)
{
returnl.y<</FONT> r.y ||(l.y== r.y &&l.x<</FONT> r.x);}
int
graham(point pnt[], intn,point res[])
 
{
inti, len, k= 0, top= 1;
sort(pnt,pnt +n);
 
if(n== 0)
return 0;
res[0]= pnt[0];
if(n== 1)
 
return1;
res[1]= pnt[1];
if
(n== 2) return2;
res
[2]= pnt[2];
for(i= 2; i<</FONT> n; i++)
 
{while(top&& mult(pnt[i],res[top],res[top-1]))top--;res[++top]= pnt[i]; }
 
len= top;
 
res[++top]= pnt[n -2];
for(i= n- 3; i>= 0; i--)
 
{while(top!=len&& mult(pnt[i],res[top],res[top-1]))
    top--;
    res[++top]= pnt[i];
}
 
returntop; // 返回凸包中点的个数}

 


凸包
0 0
原创粉丝点击