Mindis 2019百度之星初赛第一轮(建图 最短路)

本文探讨了一种解决矩阵覆盖问题的算法,通过离散化坐标、构建网格图及使用二维差分技术,实现了对被多个矩形覆盖区域的速度调整,从而计算从起点到终点的最短时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

original link - http://acm.hdu.edu.cn/showproblem.php?pid=6670

题意:

给出n个矩阵,起点到终点,可以往四个方向移动,被kkk个矩形覆盖时,速度为k+1k+1k+1,边也算覆盖。求最短时间。

解析:

将所有坐标离散化,建网格图(400*400)。

两个点之间的距离已经可以计算了,关键是被多少个矩形覆盖。

首先我们二维差分一下,处理出每个点被覆盖的次数。但是两个点之间的线段被覆盖几次还是不能算出来。所以我们将坐标两倍化,取两个点中间的点来判断被覆盖的次数。

这个不是简单的bfsbfsbfs,最近的点跑到终点的路径可能很长,所以不能跑到就breakbreakbreak

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define LL long long

const int maxn=900;
const int di[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

struct Uni{
    int a[maxn];
    int num=0;
    void push(int val){
        a[++num]=val;
    }
    void init(){
        sort(a+1,a+1+num);
        num=unique(a+1,a+1+num)-a-1;
    }
    int pos(int val){
        return lower_bound(a+1,a+1+num,val)-a;
    }
    int ori(int pos){
        return a[pos];
    }
}X,Y;

struct point{
    int x,y;
};
struct node{
    point a,b;
}e[maxn];

struct Node{
    int x,y;
    double dis;
    Node(int x,int y,double dis):x(x),y(y),dis(dis){}
    bool operator<(const Node&A)const{
        return dis>A.dis;
    }
};



LL val[maxn][maxn];
double dis[maxn][maxn];
bool vis[maxn][maxn];

//pair<int,int> pre[maxn][maxn];

int main(){
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    int t;scanf("%d",&t);
    while(t--){
        memset(val,0,sizeof val);
        X.num=Y.num=0;
        int n;scanf("%d",&n);
        point st,en;
        rep(i,1,n+1){
            scanf("%d%d%d%d",&e[i].a.x,&e[i].a.y,&e[i].b.x,&e[i].b.y);
            X.push(e[i].a.x);
            X.push(e[i].b.x);
            Y.push(e[i].a.y);
            Y.push(e[i].b.y);
        }
        X.init(),Y.init();
        rep(i,1,n+1){
            int &x=e[i].a.x,&y=e[i].a.y,&xx=e[i].b.x,&yy=e[i].b.y;
            x=X.pos(x);
            y=Y.pos(y);
            xx=X.pos(xx);
            yy=Y.pos(yy);
            if(i<=n)
                val[x*2][y*2]++,
                val[x*2][yy*2+1]--,
                val[xx*2+1][y*2]--,
                val[xx*2+1][yy*2+1]++;
        }
        rep(i,1,X.num*2+1){
            rep(j,1,Y.num*2+1){
                val[i][j]+=val[i-1][j]+val[i][j-1]-val[i-1][j-1];
                dis[i][j]=1e18;
                vis[i][j]=0;
            }
        }
        st=e[n+1].a,en=e[n+1].b;
        dis[st.x][st.y]=0;
        priority_queue<Node>Q;
        Q.push(Node(st.x,st.y,0));
        while(!Q.empty()){
            Node P=Q.top();Q.pop();
            if(fabs(dis[P.x][P.y]-P.dis)>1e-9)continue;
            vis[P.x][P.y]=1;
            rep(i,0,3){
                int x=P.x+di[i][0],y=P.y+di[i][1];
                if(x<1||x>X.num||y<1||y>Y.num||vis[x][y])continue;
                LL Dis=abs(X.ori(x)-X.ori(P.x))+abs(Y.ori(y)-Y.ori(P.y));
                LL Speed=val[(x*2+P.x*2)/2][(y*2+P.y*2)/2]+1;//min(val[x][y],val[P.x][P.y])+1;
                double tim=1.0*Dis/Speed;
                if(dis[x][y]>dis[P.x][P.y]+tim){
                    dis[x][y]=dis[P.x][P.y]+tim;
                    Q.push(Node(x,y,dis[x][y]));
                    //pre[x][y]={P.x,P.y};
                }
            }
        }
        printf("%.5f\n",dis[en.x][en.y]);

        /*int x=en.x,y=en.y;
        while(1){
            printf("%d %d, dis is %.4f\n",X.ori(x),Y.ori(y),dis[x][y]);
            if(x==st.x&&y==st.y)break;
            pair<int,int> P=pre[x][y];
            x=P.first;
            y=P.second;
        }*/
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值