2019 年百度之星·程序设计大赛 - 初赛一 1003 Mindis

Mindis

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 259    Accepted Submission(s): 57


 

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

对于每组数据,输出一个小数表示答案。答案保留 5 位小数。

 

 

Sample Input

 

1 1 5 5 6 6 7 7 8 8

 

 

Sample Output

 

2.00000

 

 

Source

2019 年百度之星·程序设计大赛 - 初赛一

 

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6673 6672 6671 6670 6669 

 

分析:

我们对给定的n+1个矩形(包括起点和终点),画成一个网格图,比如,样例:

我们会得到最多(201*2)*(201*2)个点,对这些点进行建图,边为每两点之间的距离/速度,然后跑最短路就可以了。

速度的求法预处里一下(暴力求也没问题),对于每一个矩形我们我们把每一条边被矩形覆盖多少次赋值给他的临近的点(蓝色箭头),红色矩形是需要赋值的点

所以需要开两个表示横纵的赋值情况。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e6+5;
vector<int> vx,vy;
int head[N],tot;
struct node
{
    int next; //下一条边的存储下标
    int to; //这条边的终点
    double w;//权值
} edge[N*4];
void add(int u,int v,double w)
{
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}

int n,sx,sy,ex,ey;
struct Node
{
    int x1,x2,y1,y2;
} a[N];

int getidx(int x)
{
    return lower_bound(vx.begin(),vx.end(),x)-vx.begin()+1;
}
int getidy(int y)
{
    return lower_bound(vy.begin(),vy.end(),y)-vy.begin()+1;
}
double getdis(int x1,int x2,int k)
{
    return double(abs(x1-x2))/(1.0*k);
}

int cal(double x,double y)
{
    int res=1;
    for(int i=1; i<=n; i++)
    {
        if(x>=a[i].x1&&x<=a[i].x2&&y>=a[i].y1&&y<=a[i].y2)
            res++;
    }
    return res;
}

struct Rec
{
    int id; //节点编号
    double dis; //距离
    /*bool operator<(const Rec &tmp)const{
        return dis>tmp.dis;
    }  */
};
bool operator <(const Rec&a,const Rec&b)
{
    return a.dis>b.dis;
}
priority_queue<Rec> q;//重载小于号实现小根堆
int vis[N];
double dist[N];
void dijkstra()
{
    for(int i=0; i<N; i++)
        dist[i]=1e18;

    memset(vis,0,sizeof(vis));

    dist[getidx(sx)*1000+getidy(sy)]=0;
    Rec rec;
    rec.id=getidx(sx)*1000+getidy(sy);
    rec.dis=0;
    q.push(rec);
    while(!q.empty())
    {
        int u=q.top().id;

        q.pop();
        if(vis[u])
            continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=edge[i].next) //遍历以u为起点的所有边,与输入顺序相反
        {
            int v=edge[i].to;

            double w=edge[i].w;
            //  if(u==4003||u==3004)
            //cout<<u<<" "<<v<<" "<<w<<endl;
            //cout<<dist[u]<<" "<<dist[v]<<endl;
            if(dist[v]>dist[u]+w)
            {
                //cout<<u<<"*"<<v<<" "<<w<<endl;
                dist[v]=dist[u]+w;
                Rec rec;
                rec.id=v;
                rec.dis=dist[v];
                q.push(rec);
            }
        }
    }
}
int num_x[405][405],num_y[405][405];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        vx.clear();
        vy.clear();
        init();
        memset(num_x,0,sizeof(num_x));
        memset(num_y,0,sizeof(num_y));

        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
            vx.push_back(a[i].x1);
            vy.push_back(a[i].y1);
            vx.push_back(a[i].x2);
            vy.push_back(a[i].y2);
        }


        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);

        vx.push_back(sx);
        vy.push_back(sy);
        vx.push_back(ex);
        vy.push_back(ey);


        sort(vx.begin(),vx.end());
        vx.erase(unique(vx.begin(),vx.end()),vx.end());

        sort(vy.begin(),vy.end());
        vy.erase(unique(vy.begin(),vy.end()),vy.end());


        for(int i=1; i<=n; i++)
        {
        	//cout<<"*"<<i<<" "<<n<<endl;
            int l=getidx(a[i].x1),r=getidx(a[i].x2);
            int down=getidy(a[i].y1),up=getidy(a[i].y2);
            for(int j=l; j<=r; j++)
            {
                for(int k=down; k<=up; k++)
                {
                    if(j<r)
                        num_x[j][k]++;
                    if(k<up)
                        num_y[j][k]++;
                }

            }
        }
        

        for(int i=0; i<vx.size(); i++)
        {
            for(int j=0; j<vy.size(); j++)
            {

                int x1=getidx(vx[i]),y1=getidy(vy[j]);

                if(i+1<vx.size())
                {
                    int x2=getidx(vx[i+1]),y2=getidy(vy[j]);
                    double dis=getdis(vx[i],vx[i+1],num_x[x1][y1]+1);
                    //cout<<x1*1000+y1<<" "<<x2*1000+y2<<" "<<dis<<" "<<endl;
                    add(x1*1000+y1,x2*1000+y2,dis);
                    add(x2*1000+y2,x1*1000+y1,dis);
                }


                if(j+1<vy.size())
                {
                    int x3=getidx(vx[i]),y3=getidy(vy[j+1]);
                    double dis=getdis(vy[j],vy[j+1],num_y[x1][y1]+1);

                    add(x1*1000+y1,x3*1000+y3,dis);
                    add(x3*1000+y3,x1*1000+y1,dis);
                }
            }
        }

        dijkstra();
        //cout<<getidx(ex)*1000+getidy(ey)<<endl;

        printf("%.5f\n",dist[getidx(ex)*1000+getidy(ey)]);

    }
    return 0;
}
/*
100
3
1 1 2 2
1 1 2 2
1 1 2 2
1 1 2 2
*/

 

 更精炼的代码,202ms

 

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int dx[] = {0, 0, -1, 1};
const int dy[] = {1, -1, 0, 0};
const int N = 205;
int n, nx, ny, T, x[2*N], y[2*N], X1[N], X2[N], Y1[N], Y2[N];
int sx, sy, ex, ey;
int w1[2*N][2*N], w2[2*N][2*N], inq[2*N][2*N];
double d[2*N][2*N];

int work()
{
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d%d%d%d", &X1[i], &Y1[i], &X2[i], &Y2[i]);
        x[2*i] = X1[i];
        x[2*i+1] = X2[i];
        y[2*i] = Y1[i];
        y[2*i+1] = Y2[i];
    }
    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
    x[2*n] = sx;
    x[2*n+1] = ex;
    y[2*n] = sy;
    y[2*n+1] = ey;


    sort(x, x+2*n+2);
    sort(y, y+2*n+2);
    nx = unique(x, x+2*n+2) - x;
    ny = unique(y, y+2*n+2) - y;

    for (int i = 0; i < n; ++i)
    {
        X1[i] = lower_bound(x, x+nx, X1[i]) - x;
        X2[i] = lower_bound(x, x+nx, X2[i]) - x;
        Y1[i] = lower_bound(y, y+ny, Y1[i]) - y;
        Y2[i] = lower_bound(y, y+ny, Y2[i]) - y;
    }
    sx = lower_bound(x, x+nx, sx) - x;
    ex = lower_bound(x, x+nx, ex) - x;
    sy = lower_bound(y, y+ny, sy) - y;
    ey = lower_bound(y, y+ny, ey) - y;

    memset(w1, 0, sizeof w1);
    memset(w2, 0, sizeof w2);

    for (int i = 0; i < n; ++i)
    {
        for (int j = X1[i]; j <= X2[i]; ++j)
            for (int k = Y1[i]; k <= Y2[i]; ++k)
            {
                if (j < X2[i])
                    w1[j][k]++;
                if (k < Y2[i])
                    w2[j][k]++;
            }
    }

    queue<pair<int, int> > Q;
    for (int i = 0; i < nx; ++i)
        for (int j = 0; j < ny; ++j)
            d[i][j] = 1e18;
    memset(inq, 0, sizeof inq);
    d[sx][sy] = 0;
    Q.push(make_pair(sx, sy));
    inq[sx][sy] = 1;

    //for (int i = 0; i < n; ++i) printf("%d %d %d %d\n", X1[i], Y1[i], X2[i], Y2[i]);
    //printf("%d %d %d %d\n", sx, sy, ex, ey);

    while (!Q.empty())
    {
        int ux = Q.front().first;
        int uy = Q.front().second;
        Q.pop();
        inq[ux][uy] = 0;
        for (int i = 0; i < 4; ++i)
        {
            int vx = ux + dx[i];
            int vy = uy + dy[i];
            if (vx < 0 || vy < 0 || vx >= nx || vy >= ny)
                continue;
            double dist = 0;
            if (i < 2)
                dist = 1.0 * abs(y[vy] - y[uy]) / (w2[ux][min(uy,vy)] + 1);
            else
                dist = 1.0 * abs(x[ux] - x[vx]) / (w1[min(ux,vx)][uy] + 1);
            //printf("-d %d %d = %.5f\n", vx, vy, dist);
            if (d[vx][vy] > d[ux][uy] + dist)
            {
                d[vx][vy] = d[ux][uy] + dist;
                //printf(" d %d %d = %.5f\n", vx, vy, d[vx][vy] );
                if (!inq[vx][vy])
                {
                    Q.push(make_pair(vx, vy));
                    inq[vx][vy] = true;
                }
            }
        }
    }

    printf("%.5f\n", d[ex][ey]);
    return 0;
}

int main()
{
    //work();
    //while (~scanf("%d", &n)) work();
    scanf("%d", &T);
    while (T--)
        work();

    return 0;
}

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页