zoukankan      html  css  js  c++  java
  • 最短路(数据处理):HDU 5817 Ice Walls

    Have you ever played DOTA? If so, you may know the hero, Invoker. As one of the few intelligence carries, Invoker has 10 powerful abilities. One of them is the Ice Wall: Invoker generates a wall of solid ice directly in front of him, and the bitter cold emanating from it greatly slows nearby enemies and deals damage each second.

    Now consider the map as a plane. You are now at point s, and want to move to point t. But Invoker has placed N ice walls on the map. Your moving speed is 1 per second, but you need k seconds to pass an ice wall. Time is precious, you must get to point t as quickly as possible. What's the minimum time you need?

    For convenience, you can assume that all ice walls are segments (no width) either parallel to X-axis or to Y-axis. Segments are strictly disjoint (have no common point). Point s and t are not on any segment (have no common point).

    You will not be slowed when pass the end point of a segment or walk along a segment.
     

    Input

    The input begins with an integer T, indicating the number of test cases. For each case, the first line is two integers N and k (1 <= N <= 500, 0 <= k <= 10^8), indicating the number of segments and the time needed to pass an ice wall. Next N lines, each have four integers x1, y1, x2, y2, indicating two end points of a segment, (x1, y1) and (x2, y2). Next line has two integers xs and ys, representing the coordinates of starting point s. The last line also has two integers xt and yt, representing the coordinates of target point t. For every point, |x| and |y| <= 108.
     

    Output

    For each case, output one line containing the minimum time in second needed to get to t from s. The answer should be given within an absolute or relative error of 106.
     

    Sample Input

    3
    1 1
    1 0 1 2
    0 0
    2 0
    1 1
    1 -2 1 2
    0 0
    2 0
    1 3
    1 -2 1 2
    0 0
    2 0

    Sample Output

    2.000000
    3.000000
    4.472136
      
      这道题还是有些挑战的,可以一眼看出是最短路,但如何处理出点对的直接路径?
      考虑极角排序,我不会,就用三角函数的sin和cos代替,然后用bit维护,可以做到N²logN。
      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <cmath>
      6 using namespace std;
      7 const double eps=1e-10;
      8 const int N=1010,M=4000010;
      9 
     10 struct Node{int x,y,tp;}point[N],s,t,tmp;
     11 struct Data{Node t;int id;double k,d;}st[N];
     12 int hsh[2*N],bit[2*N],csh,top;double G[N][N];
     13 
     14 double Dis(Node a,Node b){
     15     return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
     16 }
     17 
     18 double K1(Node b){return 1.0*(b.x-tmp.x)/Dis(tmp,b);}
     19 double K2(Node b){return 1.0*(b.y-tmp.y)/Dis(tmp,b);}
     20 
     21 int Rk1(int tp){return tp==4?1:tp==3?3:2;}
     22 int Rk2(int tp){return tp==2?1:tp==1?3:2;}
     23 
     24 bool cmp1(Data p,Data q){ 
     25     Node a=p.t,b=q.t;
     26     if(fabs(p.k-q.k)>0)return q.k-p.k>=eps;
     27     if(a.tp==4&&b.tp==4)return q.d-p.d>=eps;
     28     if(a.tp==3&&b.tp==3)return p.d-q.d>=eps;
     29     return Rk1(a.tp)<Rk1(b.tp);
     30 }
     31 
     32 bool cmp2(Data p,Data q){ 
     33     Node a=p.t,b=q.t;
     34     if(fabs(p.k-q.k)>0)return p.k<q.k;
     35     if(a.tp==2&&b.tp==2)return p.d<q.d;
     36     if(a.tp==1&&b.tp==1)return p.d>q.d;
     37     return Rk2(a.tp)<Rk2(b.tp);
     38 }
     39 int Query(int x,int y){int ret=0;
     40     x=lower_bound(hsh+1,hsh+csh+1,x)-hsh-1;
     41     while(x){ret-=bit[x];x-=x&(-x);}
     42     y=lower_bound(hsh+1,hsh+csh+1,y)-hsh;
     43     while(y){ret+=bit[y];y-=y&(-y);}
     44     return ret;
     45 }
     46 
     47 void Add(int x,int d){
     48     x=lower_bound(hsh+1,hsh+csh+1,x)-hsh;
     49     while(x<=csh)bit[x]+=d,x+=x&(-x);
     50 }
     51 
     52 int tot,n,ice,T;
     53 void Solve1(int p){
     54     tmp=point[p];top=0;
     55     for(int i=1;i<=tot;i++){
     56         Node b=point[i];if(tmp.y<=b.y)continue;
     57         st[++top]=(Data){b,i,K1(b),Dis(tmp,b)};
     58     }sort(st+1,st+top+1,cmp1);
     59     memset(bit,0,sizeof(bit));
     60     for(int i=1;i<=top;i++){
     61         Data b=st[i];Node c=b.t;
     62         if(c.tp==4)Add(c.y,-1);
     63         G[b.id][p]+=ice*Query(c.y,tmp.y);
     64         G[p][b.id]+=ice*Query(c.y,tmp.y);
     65         if(c.tp==3)Add(c.y,1);
     66     }
     67 }
     68 
     69 void Solve2(int p){
     70     tmp=point[p];top=0;
     71     for(int i=1;i<=tot;i++){
     72         Node b=point[i];if(tmp.x<=b.x)continue;
     73         st[++top]=(Data){b,i,K2(b),Dis(tmp,b)};
     74     }sort(st+1,st+top+1,cmp2);
     75     memset(bit,0,sizeof(bit));
     76     for(int i=1;i<=top;i++){
     77         Data b=st[i];Node c=b.t;
     78         if(c.tp==2)Add(c.x,-1);
     79         G[b.id][p]+=ice*Query(c.x,tmp.x);
     80         G[p][b.id]+=ice*Query(c.x,tmp.x);
     81         if(c.tp==1)Add(c.x,1);
     82     }
     83 }
     84 
     85 int vis[N];double dis[N];
     86 double Dij(int s,int t){
     87     for(int i=0;i<N;i++)
     88     dis[i]=1e20,vis[i]=0;dis[s]=0;
     89     for(int i=1,p;i<=tot;i++){p=0;
     90         for(int j=1;j<=tot;j++)
     91             if(!vis[j]&&dis[p]>dis[j])p=j;
     92         vis[p]=true;
     93         for(int j=1;j<=tot;j++)
     94             dis[j]=min(dis[j],dis[p]+G[p][j]);        
     95     }
     96     return dis[t];
     97 }
     98 
     99 void Initial(){
    100     memset(G,0,sizeof(G));
    101     tot=csh=0;
    102 }
    103 
    104 int main(){
    105     scanf("%d",&T);
    106     while(T--){
    107         scanf("%d%d",&n,&ice);Initial();
    108         for(int i=1,x1,y1,x2,y2;i<=n;i++){
    109             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    110             hsh[++csh]=x1;hsh[++csh]=x2;
    111             hsh[++csh]=y1;hsh[++csh]=y2;
    112             if(x1==x2&&y1==y2)continue;
    113             if(x1==x2){
    114                 if(y1>y2)swap(y1,y2);
    115                 point[++tot]=(Node){x1,y1,1};
    116                 point[++tot]=(Node){x2,y2,2};
    117             }
    118             if(y1==y2){
    119                 if(x1>x2)swap(x1,x2);
    120                 point[++tot]=(Node){x1,y1,3};
    121                 point[++tot]=(Node){x2,y2,4};
    122             }
    123         }
    124         
    125         scanf("%d%d",&s.x,&s.y);
    126         scanf("%d%d",&t.x,&t.y);
    127 
    128         hsh[++csh]=s.x;hsh[++csh]=s.y;
    129         hsh[++csh]=t.x;hsh[++csh]=t.y;
    130         
    131         sort(hsh+1,hsh+csh+1);
    132         csh=unique(hsh+1,hsh+csh+1)-hsh-1;
    133             
    134         point[++tot]=(Node){s.x,s.y,0};
    135         point[++tot]=(Node){t.x,t.y,0};
    136         
    137         for(int i=1;i<=tot;i++)Solve1(i);
    138         for(int i=1;i<=tot;i++)Solve2(i);    
    139         
    140         for(int i=1;i<=tot;i++)
    141             for(int j=1;j<=tot;j++)
    142                 G[i][j]+=Dis(point[i],point[j]);
    143         printf("%.6lf
    ",Dij(tot-1,tot));
    144     }
    145     return 0;
    146 }

      WA在求dis的平方上了,注意会爆int。

    附上数据生成器:

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <cstdlib>
     6 #include <ctime>
     7 using namespace std;
     8 int G[1010][1010],h[1010];
     9 int main(){
    10     srand(time(NULL));
    11     int T=1,n=500,w=1000;
    12     printf("%d
    ",T);
    13     while(T--){
    14         printf("%d %d
    ",n,rand()%w);
    15         int x,y,a,b,l;
    16         for(int i=0;i<w;i++){
    17             h[i]=rand()*rand()%100000000;
    18             if(rand()%2)h[i]*=-1;
    19         }
    20         sort(h,h+w);
    21         memset(G,0,sizeof(G));
    22         for(int i=1;i<=n;i++){
    23             while(true){
    24                 x=rand()%w;y=rand()%w;
    25                 while(G[x][y])x=rand()%w,y=rand()%w;
    26                 if(rand()%2){
    27                     a=x;l=0;
    28                     while(y+l+1<=w&&G[x][y+l]==0)l++;
    29                     if(l==1)continue;b=y+rand()%(l-1)+1;
    30                 }
    31                 else{
    32                     b=y;l=0;
    33                     while(x+l+1<=w&&G[x+l][y]==0)l++;
    34                     if(l==1)continue;a=x+rand()%(l-1)+1;
    35                 }
    36                 for(int j=x;j<=a;j++)
    37                     for(int k=y;k<=b;k++)
    38                         G[j][k]=1;
    39                 printf("%d %d %d %d
    ",h[x],h[y],h[a],h[b]);
    40                 break;        
    41             }
    42         }
    43         x=rand()%w;y=rand()%w;
    44         while(G[x][y])x=rand()%w,y=rand()%w;
    45         printf("%d %d
    ",h[x],h[y]);G[x][y]=1;
    46         x=rand()%w;y=rand()%w;
    47         while(G[x][y])x=rand()%w,y=rand()%w;
    48         printf("%d %d
    ",h[x],h[y]);
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    PHP数据库备份文件分卷导入的实现思路
    用delphi如何实现启动停止windows服务
    【创意logo】第23个世界无烟日 让烟草远离女性
    修改“windows xp资源管理器”的默认打开路径
    PHP百行代码快速构建简易聊天室
    简单的方法实现判断Mysql内某个字段Fields是否存在
    Blackhand的插件管理部分
    PHP 与 ASP.NET 正面交锋
    C语言运算符
    功能齐全的发送邮件类
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5991692.html
Copyright © 2011-2022 走看看