题目链接:https://vjudge.net/contest/202436#problem/B
题意:已知B(1≤B≤50)个信号站和C(1≤C≤50)座城市的坐标,坐标的绝对值不大于1000,每个城市使用最近的信号站。给定R(1≤R≤250)条连接城市线路的描述和Q(1≤Q≤10)个查询,求相应两城市间通信时最少需要转换信号站的次数。
解法:
#include <bits/stdc++.h>
using namespace std;
struct node{
int x,y;
};
const int MaxB = 50;
const int MaxC = 50;
const int MaxS = 50*50;
int B, C, R, Q;
node BTS[MaxB], city[MaxC];
int S[MaxC][MaxC];
double dis(double x1, double y1, double x2, double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int area(double x, double y){
int i,k;
double minn,tmp;
minn = dis(x,y,BTS[0].x,BTS[0].y);
k=0;
for(int i=1;i<B;i++){
tmp = dis(x,y,BTS[i].x,BTS[i].y);
if(tmp<minn){
minn = tmp;
k = i;
}
}
return k;
}
int get_switch(double x1, double y1, double x2, double y2){
if(area(x1,y1)==area(x2,y2)) return 0;
if(dis(x1,y1,x2,y2)<1e-6) return 1;
return get_switch(x1,y1,(x1+x2)/2,(y1+y2)/2)+get_switch((x1+x2)/2,(y1+y2)/2, x2,y2);
}
int main(){
int ks = 0;
while(~scanf("%d%d%d%d",&B,&C,&R,&Q)){
if(B==0&&C==0&&R==0&&Q==0) break;
for(int i=0; i<B; i++) scanf("%d%d", &BTS[i].x,&BTS[i].y);
for(int i=0; i<C; i++) scanf("%d%d", &city[i].x,&city[i].y);
memset(S, 0, sizeof(S));
for(int i=0; i<R; i++){
int x, y;
scanf("%d %d", &x,&y);
x--;
y--;
S[x][y]=S[y][x]=1;
}
for(int i=0; i<C; i++){
for(int j=i+1; j<C; j++){
if(S[i][j]==0) S[i][j]=MaxS;
else S[i][j] = get_switch(city[i].x,city[i].y,city[j].x,city[j].y);
S[j][i]=S[i][j];
}
}
for(int i=0;i<C;i++) S[i][i]=0;
for(int k=0; k<C; k++)
for(int i=0; i<C; i++)
for(int j=0; j<C; j++)
if(S[i][j]>S[i][k]+S[k][j])
S[i][j] = S[i][k]+S[k][j];
printf("Case %d:\n", ++ks);
for(int i=0; i<Q; i++){
int x, y;
scanf("%d %d", &x,&y);
x--;
y--;
if(S[x][y]>=MaxS) puts("Impossible");
else printf("%d\n", S[x][y]);
}
}
}