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;
    }
    

      

  • 相关阅读:
    Chrome开发者工具中Elements(元素)断点的用途
    最简单的SAP云平台开发教程
    Java实现 LeetCode 495 提莫攻击
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 492 构造矩形
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403236.html
Copyright © 2011-2022 走看看