BZOJ 1185 凸包+旋转卡壳
Posted konjak魔芋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1185 凸包+旋转卡壳相关的知识,希望对你有一定的参考价值。
Description
【分析】
打计算几何真的可以哭出来。。。
跟那个求线段最远点差不多,这题弄三个东西转一转,一个表示左端最远点,一个表示右端最远点,一个表示上面最远点。
左右两边的最远点用点积判断,上方最远点用差积判断。
【向量是最好的解决平面几何问题的,不要画图!!!哭!!!
输出那里,用的是向量加减法,乘一个比例系数,然后还用到了垂直单位向量。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define Maxn 50010 9 10 const double eps=0.0000001; 11 const double INF=999999999; 12 13 struct P 14 { 15 double x,y; 16 }a[Maxn],t[Maxn]; 17 int len,n; 18 19 P operator - (P x,P y) 20 { 21 P tt; 22 tt.x=x.x-y.x; 23 tt.y=x.y-y.y; 24 return tt; 25 } 26 27 P operator * (P x,double y) 28 { 29 P tt; 30 tt.x=x.x*y; 31 tt.y=x.y*y; 32 return tt; 33 } 34 35 P operator + (P x,P y) 36 { 37 P tt; 38 tt.x=x.x+y.x; 39 tt.y=x.y+y.y; 40 return tt; 41 } 42 43 double myabs(double x) {return x>0?x:-x;} 44 45 int fbs(double x) 46 { 47 if(myabs(x)<=eps) return 0; 48 return x<0?-1:1; 49 } 50 51 double Dot(P x,P y) {return x.x*y.x+x.y*y.y;} 52 double Cross(P x,P y) {return x.x*y.y-x.y*y.x;} 53 bool cmp(P x,P y) {return fbs(x.x-y.x)==0?(x.y<y.y):(x.x<y.x);} 54 55 void chull() 56 { 57 sort(a+1,a+1+n,cmp); 58 len=0; 59 for(int i=1;i<=n;i++) 60 { 61 while(len>1&&Cross(t[len]-t[len-1],a[i]-t[len])<=0) len--; 62 t[++len]=a[i]; 63 } 64 int k=len; 65 for(int i=n-1;i>=1;i--) 66 { 67 while(len>k&&Cross(t[len]-t[len-1],a[i]-t[len])<=0) len--; 68 t[++len]=a[i]; 69 }len--; 70 t[0]=t[len]; 71 } 72 73 void output() 74 { 75 for(int i=0;i<len;i++) 76 { 77 printf("%lf %lf\\n",t[i].x,t[i].y); 78 }printf("\\n"); 79 } 80 81 double ans; 82 P op[5]; 83 84 void RC() 85 { 86 double L,R,H,D; 87 ans=INF; 88 int l=1,r=1,h=1; 89 for(int i=0;i<len;i++) 90 { 91 int j=(i+1)%len; 92 // l=i;r=j;h=j; 93 // printf("%lf %lf\\n",(t[h+1]-t[i]).x,(t[h+1]-t[i]).y); 94 // printf("%lf %lf\\n",(t[h+1]-t[j]).x,(t[h+1]-t[j]).y); 95 while(Cross(t[h]-t[i],t[h]-t[j])<=Cross(t[h+1]-t[i],t[h+1]-t[j])) h=(h+1)%len; 96 while(Dot(t[i]-t[j],t[r]-t[j])>=Dot(t[i]-t[j],t[r+1]-t[j])) r=(r+1)%len; 97 if(i==0) l=r; 98 99 // printf("%lf %lf\\n",Dot(t[j]-t[i],t[l]-t[i]),Dot(t[j]-t[i],t[l+1]-t[i])); 100 while(Dot(t[j]-t[i],t[l]-t[i])>=Dot(t[j]-t[i],t[l+1]-t[i])) l=(l+1)%len; 101 102 D=sqrt(Dot(t[i]-t[j],t[i]-t[j])); 103 H=Cross(t[h]-t[i],t[h]-t[j])/D; 104 L=-Dot(t[j]-t[i],t[l]-t[i])/D; 105 R=-Dot(t[i]-t[j],t[r]-t[j])/D; 106 107 // printf("**%lf %lf %lf %lf\\n",D,H,L,R); 108 109 double now=(R+L+D)*H; 110 // printf("%lf %lf %d %d %d %lf\\n",t[i].x,t[i].y,l,r,h,now); 111 if(now<ans) 112 { 113 ans=now; 114 op[0]=t[i]-(t[j]-t[i])*(L/D); 115 op[1]=t[j]-(t[i]-t[j])*(R/D); 116 P tt; 117 tt.x=(t[i]-t[j]).y;tt.y=-(t[i]-t[j]).x; 118 op[2]=op[1]+tt*(H/D); 119 op[3]=op[0]+tt*(H/D); 120 // op[0]=t[i];op[1]=t[j];op[2]=t[r];op[3]=t[l]; 121 } 122 } 123 } 124 125 int main() 126 { 127 scanf("%d",&n); 128 for(int i=1;i<=n;i++) 129 { 130 scanf("%lf%lf",&a[i].x,&a[i].y); 131 } 132 chull(); 133 // output(); 134 RC(); 135 int fr=0; 136 for(int i=1;i<4;i++) if(op[i].y<op[fr].y||fbs(op[fr].y-op[i].y)==0&&op[i].x<op[i].x) fr=i; 137 printf("%.5lf\\n",ans); 138 for(int i=0;i<4;i++) 139 { 140 if(fbs(op[i].x)==0) op[i].x=0; 141 if(fbs(op[i].y)==0) op[i].y=0; 142 } 143 // for(int i=0;i<4;i++) op[i].x=myabs(op[i].x),op[i].y=myabs(op[i].y); 144 for(int i=0;i<4;i++) 145 { 146 printf("%.5lf %.5lf\\n",op[(fr+i)%4].x,op[(fr+i)%4].y); 147 } 148 return 0; 149 }
调试过程不删了,心酸。。
2016-12-15 16:55:18
以上是关于BZOJ 1185 凸包+旋转卡壳的主要内容,如果未能解决你的问题,请参考以下文章