• 最短路(数据处理):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 }
  • 相关阅读:
    网络数据处理
    进程间通信和网络
    附加的操作系统服务
    通用操作系统服务
    UIScrollView 子控件的自动布局经验
    UIImage 添加水印
    数据类型
    ios 获取手机的IP地址
    UILAbel 设置了attributedText 后省略号不显示
    swift
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5991692.html
Copyright © 2020-2023  润新知