HDU 4455 Stealing a Cake(计算几何 点到圆 到矩形距离)

来源:互联网 发布:ubuntu 编译c 编辑:程序博客网 时间:2024/05/22 13:41

表示这个题目很坑,竟然普通的枚举角度也能过,在现场如果没敢这么干的童鞋肯定后悔死了,不过直接枚举跑的时间还是没三分枚举快的


三分枚举的思想其实和二分差不多,具体为什么对,看看代码是怎么枚举的,稍微想想就能明白了!


直接枚举:

#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#define eps 1e-8using namespace std;#define PI acos(-1.0)struct point{    double x;    double y;    point(double a=0,double b=0):x(a),y(b){}}a,b,c,d,pos,temp1,temp2,start;double r;double cross(point p0, point p1, point p2)//j计算差乘{   return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double disptoseg(point p,point l1,point l2){    point t=p;    t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;    if(cross(l1,t,p)*cross(l2,t,p)>eps)    return dis(p,l1) < dis(p,l2) ? dis(p,l1):dis(p,l2);    return fabs(cross(p,l1,l2)/dis(l1,l2));}double distotri(point p){    return min(disptoseg(p,a,b),min(disptoseg(p,b,d),min(disptoseg(p,d,c),disptoseg(p,c,a))));}point make_p(double l){    return point(pos.x+r*cos(l),pos.y+r*sin(l));}double find_dis(point p){    return dis(p,start)+distotri(p);}double find_ans(){double ans=1e10;double mid=0;double over=PI*2,k;point p;for(mid=0;mid<=over;mid+=1e-3){    p=make_p(mid);    k=find_dis(p);    if(ans > k)    ans=k;}return ans;}int main(){    while(scanf("%lf%lf",&start.x,&start.y))    {        if(start.x==0 && start.y==0)        return 0;        scanf("%lf%lf%lf",&pos.x,&pos.y,&r);        scanf("%lf%lf%lf%lf",&temp1.x,&temp1.y,&temp2.x,&temp2.y);        if(temp1.x > temp2.x)        c=temp1,temp1=temp2,temp2=c;        if(temp1.y > temp2.y)        a=temp1,d=temp2,b.x=d.x,b.y=a.y,c.x=a.x,c.y=d.y;        else        c=temp1,b=temp2,a.x=c.x,a.y=b.y,d.x=b.x,d.y=c.y;        printf("%.2lf\n",find_ans());    }    return 0;}

三分枚举:

#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#define eps 1e-8using namespace std;#define PI acos(-1.0)struct point{    double x;    double y;    point(double a=0,double b=0):x(a),y(b){}}a,b,c,d,pos,temp1,temp2,start;double r;double cross(point p0, point p1, point p2)//j计算差乘{   return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double disptoseg(point p,point l1,point l2){    point t=p;    t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;    if(cross(l1,t,p)*cross(l2,t,p)>eps)    return dis(p,l1) < dis(p,l2) ? dis(p,l1):dis(p,l2);    return fabs(cross(p,l1,l2)/dis(l1,l2));}double distotri(point p){    return min(disptoseg(p,a,b),min(disptoseg(p,b,d),min(disptoseg(p,d,c),disptoseg(p,c,a))));}point make_p(double l){    return point(pos.x+r*cos(l),pos.y+r*sin(l));}double find_dis(point p){    return dis(p,start)+distotri(p);}double find_ans(){double l,r,ans1,ans2,t_2,t_4;l=0,r=PI;double mid_2,mid_4;point p_2,p_4;while(r-l>=eps){    mid_2=(l+r)/2;    mid_4=(mid_2+r)/2;    p_2=make_p(mid_2);    p_4=make_p(mid_4);    t_2=find_dis(p_2);    t_4=find_dis(p_4);    if(t_2 > t_4)    l=mid_2;    else    r=mid_4;}p_2=make_p(l);ans1=find_dis(p_2);l=PI,r=PI*2;while(r-l>=eps){    mid_2=(l+r)/2;    mid_4=(mid_2+r)/2;    p_2=make_p(mid_2);    p_4=make_p(mid_4);    t_2=find_dis(p_2);    t_4=find_dis(p_4);    if(t_2 > t_4)    l=mid_2;    else    r=mid_4;}p_2=make_p(l);ans2=find_dis(p_2);return min(ans1,ans2);}int main(){    while(scanf("%lf%lf",&start.x,&start.y))    {        if(start.x==0 && start.y==0)        return 0;        scanf("%lf%lf%lf",&pos.x,&pos.y,&r);        scanf("%lf%lf%lf%lf",&temp1.x,&temp1.y,&temp2.x,&temp2.y);        if(temp1.x > temp2.x)        c=temp1,temp1=temp2,temp2=c;        if(temp1.y > temp2.y)        a=temp1,d=temp2,b.x=d.x,b.y=a.y,c.x=a.x,c.y=d.y;        else        c=temp1,b=temp2,a.x=c.x,a.y=b.y,d.x=b.x,d.y=c.y;        printf("%.2lf\n",find_ans());    }    return 0;}