hdu 4454 Stealing a Cake(计算几何:最短距离、枚举/三分)

题意:已知起点、圆、矩形,要求计算从起点开始,经过圆(和圆上任一点接触即可),到达矩形的路径的最短距离。(可以穿过园)。

分析:没什么好的方法,凭感觉圆上的每个点对应最短距离,应该是一个凸函数,用三分来解。不过应该是分成两部分,用两次三分来解。具体原因不明,通过实验只能得出三分必须是针对一个凸函数,很明显,从0~2*pi不是一个凸函数,但同理,0~pi,pi~2*pi也不一定是个凸函数。个人认为,网络上流传的[0,pi][pi,2*pi]这种分法,并不存在合理性。继续思考= =

    另外,直接暴力枚举也是能过的。

错误:分析圆上的点与矩形的位置关系写挫了,虽然现在还是研究不明白到底出了什么问题,应该是边界吧。

 1 double rec(double x,double y)
 2 {
 3     check();
 4     if(x-xi<eps&&y-yj>eps)
 5         return len(x,y,xi,yj);
 6     else if(x-xi<eps&&y-yi<eps)
 7         return len(x,y,xi,yi);
 8     else if(x-xj>eps&&y-yj>eps)
 9         return len(x,y,xj,yj);
10     else if(x-xj>eps&&y-yi<eps)
11         return len(x,y,xj,yj);
12 
13     if(x-xi>eps&&x-xj<eps)
14         if(y-yj>eps)
15             return fabs(y-yj);
16         else if(y-yi<eps)
17             return fabs(yi-y);
18     else if(y-yi>eps&&y-yj<eps)
19         if(x-xi<eps)
20             return fabs(xi-x);
21         else if(x-xj>eps)
22             return fabs(x-xj);
23 }
错误的写法
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const double pi=acos(-1.0);
  9 const double eps=1e-10;
 10 
 11 double sx,sy;
 12 double rx,ry,r;
 13 double xi,yi,xj,yj;
 14 
 15 double degree()
 16 {
 17     return atan((ry-sy)/(rx-sx));
 18 }
 19 
 20 double len(double x,double y,double a,double b)
 21 {
 22     return sqrt((x-a)*(x-a)+(y-b)*(y-b));
 23 }
 24 
 25 void change(double& x,double &y)
 26 {
 27     double p;
 28     p=x;
 29     x=y;
 30     y=p;
 31 }
 32 
 33 void check()
 34 {
 35     if(xi>xj)
 36         change(xi,xj);
 37     if(yi>yj)
 38         change(yi,yj);
 39 }
 40 
 41 double rec(double x,double y)
 42 {
 43     double lenx=0,leny=0;
 44     check();
 45     if(x<xi)
 46         lenx=xi-x;
 47     else if(x>xj)
 48         lenx=x-xj;
 49     if(y<yi)
 50         leny=yi-y;
 51     else if(y>yj)
 52         leny=y-yj;
 53     return sqrt(lenx*lenx+leny*leny);
 54 }
 55 
 56 double f(double m)
 57 {
 58     double dx=rx+r*cos(m);
 59     double dy=ry+r*sin(m);
 60 
 61     double len1=len(dx,dy,sx,sy);
 62     double len2=rec(dx,dy);
 63 
 64     return len1+len2;
 65 }
 66 
 67 int main()
 68 {
 69     int n;
 70     while(~scanf("%lf%lf",&sx,&sy))
 71     {
 72         if(fabs(sx)<eps&&fabs(sy)<eps)
 73             return 0;
 74         scanf("%lf%lf%lf",&rx,&ry,&r);
 75         scanf("%lf%lf%lf%lf",&xi,&yi,&xj,&yj);
 76 
 77         double l=degree(),r=l+pi;
 78         while(fabs(r-l)>eps)
 79         {
 80             double m1=l+(r-l)/3;
 81             double m2=r-(r-l)/3;
 82             if(f(m1)<f(m2))
 83                 r=m2;
 84             else
 85                 l=m1;
 86         }
 87         double l1=l;
 88         l=degree()+pi;r=l+pi;
 89         while(fabs(r-l)>eps)
 90         {
 91             double m1=l+(r-l)/3;
 92             double m2=r-(r-l)/3;
 93             if(f(m1)<f(m2))
 94                 r=m2;
 95             else
 96                 l=m1;
 97         }
 98         double l2=l;
 99         printf("%.2f\n",min(f(l1),f(l2)));
100     }
101     return 0;
102 }
View Code

暴力枚举,奇葩的精度。不过相比较而言,这个算法根据有可信度。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const double INF=1e10;
 9 const double pi=acos(-1.0);
10 const double eps=1e-10;
11 
12 double sx,sy;
13 double rx,ry,r;
14 double xi,yi,xj,yj;
15 
16 double len(double x,double y,double a,double b)
17 {
18     return sqrt((x-a)*(x-a)+(y-b)*(y-b));
19 }
20 
21 void change(double& x,double &y)
22 {
23     double p;
24     p=x;
25     x=y;
26     y=p;
27 }
28 
29 void check()
30 {
31     if(xi>xj)
32         change(xi,xj);
33     if(yi>yj)
34         change(yi,yj);
35 }
36 
37 double rec(double x,double y)
38 {
39     double lenx=0,leny=0;
40     check();
41     if(x<xi)
42         lenx=xi-x;
43     else if(x>xj)
44         lenx=x-xj;
45     if(y<yi)
46         leny=yi-y;
47     else if(y>yj)
48         leny=y-yj;
49     return sqrt(lenx*lenx+leny*leny);
50 }
51 
52 double f(double m)
53 {
54     double dx=rx+r*cos(m);
55     double dy=ry+r*sin(m);
56 
57     double len1=len(dx,dy,sx,sy);
58     double len2=rec(dx,dy);
59 
60     return len1+len2;
61 }
62 
63 int main()
64 {
65     int n;
66     while(~scanf("%lf%lf",&sx,&sy))
67     {
68         if(fabs(sx)<eps&&fabs(sy)<eps)
69             return 0;
70         scanf("%lf%lf%lf",&rx,&ry,&r);
71         scanf("%lf%lf%lf%lf",&xi,&yi,&xj,&yj);
72 
73         double m=INF;
74         for(double i=0;i<=360;i+=0.01)
75         {
76             m=min(m,f(i/180*pi));
77         }
78         printf("%.2f\n",m);
79     }
80     return 0;
81 }
View Code

 

posted @ 2013-10-04 19:42  Thousand Sunny  阅读(232)  评论(0编辑  收藏  举报