凸包

凸包凸包
 
A - Surround the Trees
Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

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、排序時,對於極角相同的點,把距離小的排在前面比較好。這樣求凸包時,可以把共線的點全部刪掉,只保留距離最大的那個點。
      否則,求凸包時,程序會把這些共線的點全部加入凸包,使凸包上的點增加。(小優化)

  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. using namespace std;  
  6.   
  7. #define N 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 C = Cross(P[0],p1,P[0],p2);  
  29.     return C ? 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. }   
凸包模板
//凸包struct point{ double x, y;};
 
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 <</FONT> (const point &l, const point &r)
{
return l.y <</FONT> r.y || (l.y == r.y && l.x <</FONT> r.x);}
int
graham(point pnt[], intn, point res[])
 
{
int i, len, k = 0, top = 1;
sort(pnt, pnt + n);
 
if(n == 0)
return 0;
res[0] = pnt[0];
if(n == 1)
 
return 1;
res[1] = pnt[1];
if
(n == 2) return 2;
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];
}
 
return top; // 返回凸包中點的個數}

 


凸包
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章