最短路(数据处理):HDU 5817 Ice Walls

Posted 既然选择了远方,便只顾风雨兼程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路(数据处理):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 10?6.
 

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维护,可以做到N2logN。
  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\n",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\n",T);
13     while(T--){
14         printf("%d %d\n",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\n",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\n",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\n",h[x],h[y]);
49     }
50     return 0;
51 }

 

以上是关于最短路(数据处理):HDU 5817 Ice Walls的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 4725 最短路

HDU - 4725 最短路

hdu3416 Marriage Match IV(最短路+最大流)

HDU 3499 分层图最短路+Trie树

hdu2544---最短路

hdu5740