• HDU 4667 Building Fence(2013多校7 1002题 计算几何,凸包,圆和三角形)


    Building Fence

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
    Total Submission(s): 171    Accepted Submission(s): 25
    Special Judge


    Problem Description
    Long long ago, there is a famous farmer named John. He owns a big farm and many cows. There are two kinds of cows on his farm, one is Friesian, and another one is Ayrshire. Each cow has its own territory. In detail, the territory of Friesian is a circle, and of Ayrshire is a triangle. It is obvious that each cow doesn't want their territory violated by others, so the territories won't intersect.

    Since the winter is falling, FJ has to build a fence to protect all his cows from hungry wolves, making the territory of cows in the fence. Due to the financial crisis, FJ is currently lack of money, he wants the total length of the fence minimized. So he comes to you, the greatest programmer ever for help. Please note that the part of fence don't have to be a straight line, it can be a curve if necessary.
     
    Input
    The input contains several test cases, terminated by EOF. The number of test cases does not exceed 20.
    Each test case begins with two integers N and M(0 ≤ N, M ≤ 50, N + M > 0)which denotes the number of the Friesian and Ayrshire respectively. Then follows N + M lines, each line representing the territory of the cow. Each of the first N lines contains three integers Xi, Yi, Ri(1 ≤ Ri ≤ 500),denotes the coordinates of the circle's centre and radius. Then each of the remaining M lines contains six integers X1i, Y1i, X2i, Y2i, X3i, Y3i, denotes the coordinates of the triangle vertices. The absolute value of the coordinates won't exceed 10000.
     
    Output
    For each test case, print a single line containing the minimal fence length. Your output should have an absolute error of at most 1e-3.
     
    Sample Input
    1 1 4 4 1 0 0 0 2 2 0
     
    Sample Output
    15.66692
    Hint
    Please see the sample picture for more details, the fence is highlighted with red.
     
    Source
     
    Recommend
    zhuyuanchen520
     

    标程的正解应该是找圆上的关键点。

    两圆两两的切点,和三角形上的点和圆的切点是关键点。

    然后所有点求凸包。

    如果两个关键点刚好在一个圆上,用圆弧长度代替距离。

    我的做法是没有求关键点,直接把圆均匀分成1000个点,然后就水过了。

      1 /* **********************************************
      2 Author      : kuangbin
      3 Created Time: 2013/8/13 14:13:06
      4 File Name   : F:2013ACM练习2013多校71002.cpp
      5 *********************************************** */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 using namespace std;
     19 
     20 const double eps = 1e-8;
     21 const double PI = acos(-1.0);
     22 int sgn(double x)
     23 {
     24     if(fabs(x) < eps)return 0;
     25     if(x < 0)return -1;
     26     else return 1;
     27 }
     28 struct Point
     29 {
     30     double x,y;
     31     int index;
     32     Point(){}
     33     Point(double _x,double _y,int _index)
     34     {
     35         x = _x;y = _y;index = _index;
     36     }
     37     Point(double _x,double _y)
     38     {
     39         x = _x;y = _y;
     40     }
     41     Point operator -(const Point &b)const
     42     {
     43         return Point(x - b.x,y - b.y);
     44     }
     45     //叉积
     46     double operator ^(const Point &b)const
     47     {
     48         return x*b.y - y*b.x;
     49     }
     50     //点积
     51     double operator *(const Point &b)const
     52     {
     53         return x*b.x + y*b.y;
     54     }
     55     //绕原点旋转角度B(弧度值),后x,y的变化
     56     void transXY(double B)
     57     {
     58         double tx = x,ty = y;
     59         x = tx*cos(B) - ty*sin(B);
     60         y = tx*sin(B) + ty*cos(B);
     61     }
     62 };
     63 
     64 //*两点间距离
     65 double dist(Point a,Point b)
     66 {
     67     return sqrt((a-b)*(a-b));
     68 }
     69 
     70 
     71 /*
     72  * 求凸包,Graham算法
     73  * 点的编号0~n-1
     74  * 返回凸包结果Stack[0~top-1]为凸包的编号
     75  */
     76 const int MAXN = 1010000;
     77 Point list[MAXN];
     78 int Stack[MAXN],top;
     79 //相对于list[0]的极角排序
     80 bool _cmp(Point p1,Point p2)
     81 {
     82     double tmp = (p1-list[0])^(p2-list[0]);
     83     if(sgn(tmp) > 0)return true;
     84     else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0)
     85         return true;
     86     else return false;
     87 }
     88 void Graham(int n)
     89 {
     90     Point p0;
     91     int k = 0;
     92     p0 = list[0];
     93     //找最下边的一个点
     94     for(int i = 1;i < n;i++)
     95     {
     96         if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )
     97         {
     98             p0 = list[i];
     99             k = i;
    100         }
    101     }
    102     swap(list[k],list[0]);
    103     sort(list+1,list+n,_cmp);
    104     if(n == 1)
    105     {
    106         top = 1;
    107         Stack[0] = 0;
    108         return;
    109     }
    110     if(n == 2)
    111     {
    112         top = 2;
    113         Stack[0] = 0;
    114         Stack[1] = 1;
    115         return ;
    116     }
    117     Stack[0] = 0;
    118     Stack[1] = 1;
    119     top = 2;
    120     for(int i = 2;i < n;i++)
    121     {
    122         while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)
    123             top--;
    124         Stack[top++] = i;
    125     }
    126 }
    127 const int NUM  = 500;
    128 int X[100],Y[100],R[100];
    129 int main()
    130 {
    131     //freopen("in.txt","r",stdin);
    132     //freopen("out.txt","w",stdout);
    133     int N,M;
    134     while(scanf("%d%d",&N,&M) == 2)
    135     {
    136         
    137         for(int i =0;i < N;i++)
    138         {
    139             scanf("%d%d%d",&X[i],&Y[i],&R[i]);
    140             for(int j = 0;j < NUM;j++)
    141             {
    142                 double tmp = 2*PI*j/NUM;
    143                 list[j+i*NUM] =  Point( X[i] + R[i]*cos(tmp),Y[i] + R[i]*sin(tmp),i );
    144             }
    145             
    146         }
    147         int x,y;
    148         for(int i = 0;i < M;i++)
    149         {
    150             scanf("%d%d",&x,&y);
    151             list[N*NUM+i*3] = Point(x,y,-1);
    152             scanf("%d%d",&x,&y);
    153             list[N*NUM+i*3+1] = Point(x,y,-1);    
    154             scanf("%d%d",&x,&y);
    155             list[N*NUM+i*3+2] = Point(x,y,-1);
    156         }
    157         Graham(N*NUM+M*3);
    158         double ans = 0;
    159         //cout<<top<<endl;
    160         for(int i = 0;i < top;i++)
    161         {
    162             int t1 = Stack[i];
    163             int t2 = Stack[(i+1)%top];
    164         //    cout<<t1<<" "<<t2<<endl;
    165     //        printf("%.2lf %.2lf
    ",list[t1].x,list[t2].y);
    166             if(list[t1].index != -1 && list[t2].index == list[t1].index)
    167             {
    168                 int tt = list[t1].index;
    169                 ans += R[tt]*2*PI/(NUM);
    170             }
    171             else ans += dist(list[t1],list[t2]);
    172         }
    173         printf("%.5lf
    ",ans);
    174     }
    175     return 0;
    176 }
  • 相关阅读:
    HDOJ 4248 A Famous Stone Collector DP
    Android开发系列(十九个):至SimpleAdapter设置样式
    matlab入门 蜂窝阵列
    OpenGL缓冲区
    如何在终端编辑命令
    struts2跳转类型解析
    设计模式(Facade)状态(注意事项)
    Swift与Objective-C API的交互
    Swift调用Objective C的FrameWork
    初探swift语言的学习—Object-C与Swift混编
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3255839.html
Copyright © 2020-2023  润新知