HDU - 4454: Stealing a Cake (圆上三分)
pro:给定一个蛋糕,一个矩阵房子,一只蚂蚁。最开始三者两两相离,问蚂蚁触摸到蛋糕后再触摸矩阵的最短距离。结果保留两位小数,坐标的绝对值<1e4;
sol:由于坐标不大,而且精度要求不高,不难想到可以暴力一点,直接分割圆。 假设分100000份,得到每个点到蚂蚁和矩阵的距离和,更新答案。
(虽然我想到可能会三分这个圆,但是感觉情况蛮多的,因为可能不止一轮峰值,需要剥离三分的区间。
百度了下,情况其实不多。 因为剥离区间直接把圆分为[0,pi] [pi,2pi]即可。 因为如果有两个峰值,一定在对半的圆里。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; const double pi=acos(-1.0); struct point{ double x,y; point(){} point(double xx,double yy):x(xx),y(yy){} }; struct seg{ point a; point b; }; point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y);} point operator +(point a,point b){ return point(a.x+b.x,a.y+b.y);} double det(point a,point b){ return a.x*b.y-a.y*b.x;} double dot(point a,point b){ return a.x*b.x+a.y*b.y;} seg s[maxn]; point S,C,A,B; double R; double ptoseg(point P,point A,point B) { point AP=P-A,BP=P-B; if(dot(B-A,AP)<=0) return sqrt(dot(AP,AP)); if(dot(A-B,BP)<=0) return sqrt(dot(BP,BP)); return fabs(det(AP,A-B))/sqrt(dot(A-B,A-B)); } int main() { while(~scanf("%lf%lf",&S.x,&S.y)){ if(S.x==0&&S.y==0) return 0; scanf("%lf%lf%lf",&C.x,&C.y,&R); scanf("%lf%lf",&A.x,&A.y); scanf("%lf%lf",&B.x,&B.y); s[1].a=A; s[1].b=point(A.x,B.y); s[2].a=A; s[2].b=point(B.x,A.y); s[3].a=B; s[3].b=point(B.x,A.y); s[4].a=B; s[4].b=point(A.x,B.y); double ans=100000000; int T=100000; double t=pi*2/T; rep(i,1,T){ point P; P.x=C.x+R*cos(t*i); P.y=C.y+R*sin(t*i); double tmp=sqrt(dot(P-S,P-S)); double dis=ptoseg(P,s[1].a,s[1].b); rep(i,2,4) dis=min(dis,ptoseg(P,s[i].a,s[i].b)); ans=min(ans,tmp+dis); } printf("%.2lf\n",ans); } return 0; }
It is your time to fight!