Mindis(HDU-6670)

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 8

Sample 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值