zoukankan      html  css  js  c++  java
  • Noi2011 : 智能车比赛

    假设S在T左边,那么只能往右或者上下走

    f[i]表示S到i点的最短路

    f[i]=min(f[j]+dis(i,j)(i能看到j))

    判断i能看到j就维护一个上凸壳和一个下凸壳

    时间复杂度$O(n^2)$

    代码写的有点长…

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define N 2010
    using namespace std;
    struct P{int x,y;P(){}P(int _x,int _y){x=_x,y=_y;}P operator-(const P&a){return P(x-a.x,y-a.y);}};
    inline int cross(P a,P b){return a.x*b.y-a.y*b.x;}
    inline double dis(P a,P b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    int n,i,X1[N],Y1[N],X2[N],Y2[N],xs,ys,xt,yt,st,en;
    double v,f[N][4],ans,inf=1e9;
    inline void call(int x,int y,int p,double&t){
      t=inf;
      P o(x,y),up(x,y+1),down(x,y-1),tmp;
      for(int i=p-1;i>st;i--){
        tmp=P(X2[i],Y2[i]);
        if(cross(up-o,tmp-o)>=0){//在up下边或者重合
          up=tmp;
          if(cross(down-o,tmp-o)<=0)t=min(t,f[i][3]+dis(o,tmp));//在down上边或者重合
        }
        tmp=P(X2[i],Y1[i]);
        if(cross(down-o,tmp-o)<=0){//在down上边或者重合
          down=tmp;
          if(cross(up-o,tmp-o)>=0)t=min(t,f[i][2]+dis(o,tmp));//在up下边或者重合
        }
        tmp=P(X1[i],Y2[i]);
        if(cross(up-o,tmp-o)>=0){//在up下边或者重合
          up=tmp;
          if(cross(down-o,tmp-o)<=0)t=min(t,f[i][1]+dis(o,tmp));//在down上边或者重合
        }
        tmp=P(X1[i],Y1[i]);
        if(cross(down-o,tmp-o)<=0){//在down上边或者重合
          down=tmp;
          if(cross(up-o,tmp-o)>=0)t=min(t,f[i][0]+dis(o,tmp));//在up下边或者重合
        }
      }
      tmp=P(X2[st],Y2[st]);
      if(cross(up-o,tmp-o)>=0){//在up下边或者重合
        up=tmp;
        if(cross(down-o,tmp-o)<=0)t=min(t,f[st][3]+dis(o,tmp));//在down上边或者重合
      }
      tmp=P(X2[st],Y1[st]);
      if(cross(down-o,tmp-o)<=0){//在down上边或者重合
        down=tmp;
        if(cross(up-o,tmp-o)>=0)t=min(t,f[st][2]+dis(o,tmp));//在up下边或者重合
      }
      tmp=P(xs,ys);
      if(cross(up-o,tmp-o)>=0&&cross(down-o,tmp-o)<=0)t=dis(o,tmp);//在up下边或者重合 在down上边或者重合
    }
    inline void calr(int x,int y,int p,double&t){
      t=inf;
      P o(x,y),up(x,y+1),down(x,y-1),tmp;
      tmp=P(X1[p],Y2[p]);
      if(cross(up-o,tmp-o)>=0){//在up下边或者重合
        up=tmp;
        if(cross(down-o,tmp-o)<=0)t=min(t,f[p][1]+dis(o,tmp));//在down上边或者重合
      }
      tmp=P(X1[p],Y1[p]);
      if(cross(down-o,tmp-o)<=0){//在down上边或者重合
        down=tmp;
        if(cross(up-o,tmp-o)>=0)t=min(t,f[p][0]+dis(o,tmp));//在up下边或者重合
      }
      for(int i=p-1;i>st;i--){
        tmp=P(X2[i],Y2[i]);
        if(cross(up-o,tmp-o)>=0){//在up下边或者重合
          up=tmp;
          if(cross(down-o,tmp-o)<=0)t=min(t,f[i][3]+dis(o,tmp));//在down上边或者重合
        }
        tmp=P(X2[i],Y1[i]);
        if(cross(down-o,tmp-o)<=0){//在down上边或者重合
          down=tmp;
          if(cross(up-o,tmp-o)>=0)t=min(t,f[i][2]+dis(o,tmp));//在up下边或者重合
        }
        tmp=P(X1[i],Y2[i]);
        if(cross(up-o,tmp-o)>=0){//在up下边或者重合
          up=tmp;
          if(cross(down-o,tmp-o)<=0)t=min(t,f[i][1]+dis(o,tmp));//在down上边或者重合
        }
        tmp=P(X1[i],Y1[i]);
        if(cross(down-o,tmp-o)<=0){//在down上边或者重合
          down=tmp;
          if(cross(up-o,tmp-o)>=0)t=min(t,f[i][0]+dis(o,tmp));//在up下边或者重合
        }
      }
      tmp=P(X2[st],Y2[st]);
      if(cross(up-o,tmp-o)>=0){//在up下边或者重合
        up=tmp;
        if(cross(down-o,tmp-o)<=0)t=min(t,f[st][3]+dis(o,tmp));//在down上边或者重合
      }
      tmp=P(X2[st],Y1[st]);
      if(cross(down-o,tmp-o)<=0){//在down上边或者重合
        down=tmp;
        if(cross(up-o,tmp-o)>=0)t=min(t,f[st][2]+dis(o,tmp));//在up下边或者重合
      }
      tmp=P(xs,ys);
      if(cross(up-o,tmp-o)>=0&&cross(down-o,tmp-o)<=0)t=dis(o,tmp);//在up下边或者重合 在down上边或者重合
    }
    int main(){
      scanf("%d",&n);
      for(i=1;i<=n;i++)scanf("%d%d%d%d",&X1[i],&Y1[i],&X2[i],&Y2[i]);
      scanf("%d%d%d%d",&xs,&ys,&xt,&yt);
      if(xs>xt)swap(xs,xt),swap(ys,yt);
      scanf("%lf",&v);
      for(i=1;i<=n;i++)if(X1[i]<=xs&&xs<=X2[i]&&Y1[i]<=ys&&ys<=Y2[i]){st=i;break;}
      for(i=n;i;i--)if(X1[i]<=xt&&xt<=X2[i]&&Y1[i]<=yt&&yt<=Y2[i]){en=i;break;}
      f[st][2]=dis(P(xs,ys),P(X2[st],Y1[st]));
      f[st][3]=dis(P(xs,ys),P(X2[st],Y2[st]));
      for(i=st+1;i<en;i++){
        call(X1[i],Y1[i],i,f[i][0]);
        call(X1[i],Y2[i],i,f[i][1]);
        calr(X2[i],Y1[i],i,f[i][2]);
        calr(X2[i],Y2[i],i,f[i][3]);
      }
      call(X1[en],Y1[en],en,f[en][0]);
      call(X1[en],Y2[en],en,f[en][1]);
      calr(xt,yt,en,ans);
      printf("%.10f",ans/v);
      return 0;
    }
    

      

  • 相关阅读:
    tzoj5855: 数据结构实验:最短路(SPFA)
    tzoj5779 最短路(SPFA模板)
    洛谷P3375 【模板】KMP字符串匹配(KMP)
    poj2533 The Bottom of a Graph(Tarjan+缩点)
    poj1236 Network of Schools(Tarjan+缩点)
    危险道路(Tarjan+割边/桥)
    前端开发中的浏览器兼容性问题总结
    递归应用示例
    统计单词数
    找素数的两种方法
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403236.html
Copyright © 2011-2022 走看看