Problem Description
平面上有 n 个矩形,矩形的边平行于坐标轴,现在度度熊需要操控一名角色从 A 点走到 B点。
该角色可以上下左右移动,在恰被 k 个矩形覆盖的区域,该角色的速率为 k+1 个距离/秒(矩形覆盖区域包括边界)。
请求出 A 移动到 B 最快需要多少秒。Input
第一行一个整数 T (1≤T≤5) 表示数据组数。
对于每组数据,第一行输入一个整数 n (1≤n≤200)。
接下来 n 行每行 4 个整数 x1,y1,x2,y2 (0≤x1<x2≤1000000000,0≤y1<y2≤1000000000),分别表示矩形的左下角和右上角的坐标。
最后一行四个整数 xa,ya,xb,yb ((0≤xa,xb,ya,yb≤1000000000) 代表 A 和 B 的坐标。Output
出 T 行,每行一个整数表示答案。对于每组数据,输出一个小数表示答案。答案保留 5 位小数。
Sample Input
1
1
5 5 6 6
7 7 8 8Sample Output
2.00000
思路:
题中给出的 x、y 的范围可到 1000000000,但矩形个数 n 最多直到 200,因此可以用区间离散化的思想,将所有的 x、y 的坐标保存后离散化,建立网格图,这样一来,最多只有 400*400=160000 个点,相邻两点的边就是两点之间的距离/速度
然后开两个数组,分别统计每个点在水平和垂直方向上被多少个矩形覆盖,对于每一个矩形,将每一条边被矩形覆盖的次数赋给其临近的点,这样将矩形内部的速度转为两点之间的速度,最后跑最短路即可
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
const int MOD = 1E9+7;
const int N = 400+5;
const int dx[] = {1,-1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
double dis[N][N];
bool vis[N][N];
struct Node{
int x,y;
bool operator < (const Node &rhs) const{
return dis[x][y]>=dis[rhs.x][rhs.y];
}
}node[N],st,ed;
int G[N][5];
int x[N],y[N],totX,totY;
int numY[N][N],numX[N][N];//水平与垂直方向每个顶点被矩形覆盖的距离
void bfs(int lenX,int lenY){
for(int i=1;i<=lenX;i++){
for(int j=1;j<=lenY;j++){
dis[i][j]=INF;
vis[i][j]=false;
}
}
dis[st.x][st.y]=0;
priority_queue<Node,vector<Node>,less<Node> >Q;
Q.push(st);
while(!Q.empty()){
Node now=Q.top();
Q.pop();
int nowX=now.x;
int nowY=now.y;
if(vis[nowX][nowY])
continue;
vis[nowX][nowY]=true;
for(int i=0;i<4;i++){
int nx=nowX+dx[i];
int ny=nowY+dy[i];
if(nx>totX||ny>totY||!nx||!ny||vis[nx][ny])
continue;
double temp;
if(nowX==nx)//垂直方向
temp = abs(y[nowY]-y[ny])*1.0 / numY[nowX][min(nowY,ny)];
else//水平方向
temp = abs(x[nowX]-x[nx])*1.0 / numX[min(nowX,nx)][nowY];
if(dis[nowX][nowY]+temp<dis[nx][ny]){
dis[nx][ny]=dis[nowX][nowY]+temp;
now.x=nx;
now.y=ny;
Q.push(now);
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
totX=0,totY=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=4;j++)
scanf("%d",&G[i][j]);
x[++totX]=G[i][1];
y[++totY]=G[i][2];
x[++totX]=G[i][3];
y[++totY]=G[i][4];
}
scanf("%d%d%d%d",&st.x,&st.y,&ed.x,&ed.y);
x[++totX]=st.x;
y[++totY]=st.y;
x[++totX]=ed.x;
y[++totY]=ed.y;
//离散化
sort(x+1,x+1+totX);
sort(y+1,y+1+totY);
int lenX=unique(x+1,x+1+totX)-x-1;
int lenY=unique(y+1,y+1+totY)-y-1;
for(int i=1;i<=n;i++){
G[i][1]=lower_bound(x+1,x+1+lenX,G[i][1])-x;
G[i][2]=lower_bound(y+1,y+1+lenY,G[i][2])-y;
G[i][3]=lower_bound(x+1,x+1+lenX,G[i][3])-x;
G[i][4]=lower_bound(y+1,y+1+lenY,G[i][4])-y;
}
st.x=lower_bound(x+1,x+1+lenX,st.x)-x;
st.y=lower_bound(y+1,y+1+lenY,st.y)-y;
ed.x=lower_bound(x+1,x+1+lenX,ed.x)-x;
ed.y=lower_bound(y+1,y+1+lenY,ed.y)-y;
//统计每个点被矩形覆盖次数
for(int i=1;i<=lenX;i++)
for(int j=1;j<=lenY;j++)
numX[i][j]=numY[i][j]=1;
for(int i=1;i<=n;i++){
//水平方向
for(int j=G[i][1];j<G[i][3];j++)//最右端不记录
for(int k=G[i][2];k<=G[i][4];k++)
numX[j][k]++;
//垂直方向
for(int j=G[i][1];j<=G[i][3];j++)
for(int k=G[i][2];k<G[i][4];k++)//最右端不记录
numY[j][k]++;
}
bfs(lenX,lenY);
printf("%.5lf\n",dis[ed.x][ed.y]);
}
return 0;
}