zoukankan      html  css  js  c++  java
  • HDU

    pro:给定一个N边形,然后给半径为R的圆,问是否可以放进去。  问题转化为多边形的最大内接圆半径。(N<50);

    sol:乍一看,不就是二分+半平面交验证是否有核的板子题吗。 然而事情并没有那么简单。  因为我们的多边形可能是凹多边形,而前面的方法只对凸多边形有效。 

    学习了下模拟退火的算法,这个随机算法只在最小圆覆盖的时候写过。 这里再学一下,看起来更正宗一点的。  每次在当前点的附近(R)找是否能优化,而这个R慢慢变小,使得趋紧答案的趋势更精细。 

    判定点再多边形内:同样,不能用检验是否在每条边的左边来判定,因为不是凸多边形; 我们可以用射线法搞。

    rate和次数是抄的别人的,我自己也不会分析。 感觉这个取决于数据和人品吧 

    (随机要加srand来增加随机性。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=110;
    const double pi=acos(-1.0);
    const double inf=0x7fffffff;
    struct point {
        double x,y;
        point(){}
        point(double xx,double yy):x(xx),y(yy){}
    };
    struct line{
        point s,p;
        line(){}
        line(point xx,point yy):s(xx),p(yy){}
    };
    double getdis(point w,point v){
        return sqrt((w.x-v.x)*(w.x-v.x)+(w.y-v.y)*(w.y-v.y));
    }
    point operator /(point a,double t){ return point(a.x/t,a.y/t);}
    point operator *(point a,double t){ return point(t*a.x,t*a.y);}
    point operator -(point w,point v){return point(w.x-v.x,w.y-v.y);}
    point operator +(point w,point v){return point(w.x+v.x,w.y+v.y);}
    double det(point w,point v){ return w.x*v.y-w.y*v.x;}
    double dot(point w,point v){ return w.x*v.x+w.y*v.y;}
    double ltoseg(point p,point a,point b){
        point t=p-a;
        if(dot(t,b-a)<=0) return getdis(p,a);
        else if(dot(p-b,a-b)<=0) return getdis(p,b);
        return fabs(det(t,b-a))/getdis(a,b);
    }
    point p[maxn],tp[maxn]; double dist[maxn]; int N; line L[maxn];
    bool isinside(point a)
    {
    //算法描述:首先,对于多边形的水平边不做考虑,其次,
    //对于多边形的顶点和射线相交的情况,如果该顶点时其所属的边上纵坐标较大的顶点,则计数,否则忽略该点,
    //最后,对于Q在多边形上的情形,直接判断Q是否属于多边形。
        int ncross=0;
        rep(i,0,N-1) {
            point p1=p[i],p2=p[i+1];
            if(ltoseg(a,p[i],p[i+1])==0) return true; //在线段上
            if(p1.y==p2.y) continue; //默认做水平x轴的线,所以水平线不考虑
            if(a.y<min(p1.y,p2.y)) continue; //相离不考虑
            if(a.y>max(p1.y,p2.y)) continue;
            double t=det(a-p[i],a-p[i+1]);
            if((t>=0&&p[i].y<a.y&&p[i+1].y>=a.y)||(t<=0&&p[i+1].y<a.y&&p[i].y>=a.y)) ncross++;
        }
        return (ncross&1);
    }
    double getmindis(point a)
    {
        double ans=inf;
        rep(i,0,N-1) ans=min(ans,ltoseg(a,p[i],p[i+1]));
        return ans;
    }
    int main()
    {
        srand(unsigned(time(NULL)));
        while(~scanf("%d",&N)&&N){
            double X,Y,R; X=Y=0;
            rep(i,1,N) {
                scanf("%lf%lf",&p[i].x,&p[i].y);
                X=max(X,p[i].x);
                Y=max(Y,p[i].y);
            }
            p[0]=p[N];
            rep(i,0,N-1) L[i]=line(p[i],p[i+1]-p[i]);
            scanf("%lf",&R);
            int maxt=min(N,20);
            rep(i,0,maxt-1){
                tp[i]=(p[i]+p[i+1])/2;
                dist[i]=0;
            }
            double step=min(X,Y);
            const int maxd=10;
            const double rate=0.55;
            bool flag=0;
            const double EPS2=1e-6;
            while(step>EPS2&&!flag){
                rep(i,0,maxt-1){
                    rep(j,0,maxd-1){
                        double d=rand()%360/360.0*2*pi;
                        point next=tp[i];
                        next.x+=step*sin(d);
                        next.y+=step*cos(d);
                        if(!isinside(next)) continue;
                        double tdis=getmindis(next);
                        if(tdis+EPS2>dist[i]){
                            dist[i]=tdis; tp[i]=next;
                        }
                        if(tdis+EPS2>=R){
                            flag=1; break;
                        }
                    }
                }
                step*=rate;
            }
            if(flag) puts("Yes");
            else puts("No");
        }
        return 0;
    }
  • 相关阅读:
    .Net开发中不太常用的DLL及用法
    JT8082019协议,协议消息ID
    分享一个dotnet自动发布Docker的脚本
    winform下UserControl未标记为可序列化问题
    VS常用设置
    NuGet修改默认包保存的位置
    cooking构建工具报错MSBUILD :error MSB4132解决办法
    62进制(非大数除法实现)
    解决System.Data.OracleClient requires Oracle client software version 8.1.7 or greater 问题(转)
    jQuery多选列表框插件Multiselect
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10991200.html
Copyright © 2011-2022 走看看