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

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

题意:

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

解析:

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

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

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

这个不是简单的 b f s bfs bfs,最近的点跑到终点的路径可能很长,所以不能跑到就 b r e a k break break

代码:

#include
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 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 P=pre[x][y];
            x=P.first;
            y=P.second;
        }*/
    }
}

你可能感兴趣的:(图论/搜索)