bzoj 4793: [CERC2016]Hangar Hurdles

版权声明:本文为博主原创文章,爱转载的表明出处就好. https://blog.csdn.net/qq_36797743/article/details/81353106

题意

你正在评估一些关于一个巨型飞机仓库的建设计划。飞机仓库的地面可以表示为n行n列的网格图,其中每个格子要么是空的,要么有障碍物。行从上到下依次被编号为1到n,列从左到右依次被编号为1到n。存放飞机零件的大型集装箱能在飞机仓库的地面上自由移动是很重要的。我们可以将每个集装箱看作一个以某个格子为中心的边平行于坐标轴的正方形。对于一个奇数k,一个尺寸为k的集装箱是一个包含k行k列的正方形。一个集装箱的坐标为其中心格子的坐标。集装箱可以向上下左右移动,但不能碰到障碍物,且不能移出仓库的边界。给定q对格子A_k和B_k,对于每对格子,请找到能从A_k移动到B_k的集装箱的最大尺寸,注意这个尺寸也要是一个奇数。

题解

容易看出这是一个最小生成树。。
一开始看错了。。以为只需要一开始的箱子包含这个点就可以了。。然后我不知道怎么建图。。
想了很久,真是没救了
一直在想怎么剖分一个矩形。。然后怎么连起来
瞄了一眼题解,发现并不一样啊。
然后就很简单了
我是SB
其实每一个维护一个他是中心的最大,然后两点间的最小值最大就是答案了
最小生成树用启发式合并可以保证树高是log的
然后就没有了。。

CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005;
int n,m,q;
char ss[N][N];
int f[N][N];
int tx[8]={-1,-1,-1,0,0,1,1,1};
int ty[8]={-1,0,1,-1,1,-1,0,1};
void bfs ()
{
    memset(f,-1,sizeof(f));
    queue<pair<int,int> > q;
    for (int u=1;u<=n;u++)
        for (int i=1;i<=n;i++)
            if (ss[u][i]=='#')
            {
                f[u][i]=0;
                q.push(make_pair(u,i));
            }
    for (int u=1;u<=n;u++)
    {
        f[u][0]=f[0][u]=f[n+1][u]=f[u][n+1]=0;
        q.push(make_pair(u,0));
        q.push(make_pair(0,u));
        q.push(make_pair(n+1,u));
        q.push(make_pair(u,n+1));
    }
    while (!q.empty())
    {
        int x=q.front().first,y=q.front().second;q.pop();
        for (int u=0;u<8;u++)
        {
            int xx=x+tx[u],yy=y+ty[u];
            if (xx>=1&&xx<=n&&yy>=1&&yy<=n&&f[xx][yy]==-1)
            {
                f[xx][yy]=f[x][y]+1;
                q.push(make_pair(xx,yy));
            }
        }
    }
}
pair<int,pair<int,int> > s[N*N];
int P (int x,int y) {return (x-1)*n+y;}
int dep[N*N],fa[N*N],tim[N*N];
bool cmp (pair<int,pair<int,int> > x,pair<int,pair<int,int> > y)    {return x>y;}
int find_fa (int x)
{
    while (fa[x]!=x) x=fa[x];
    return fa[x];
}
void link (int x,int y,int t)
{
    if (x==y) return ;
    if (dep[x]>dep[y]) swap(x,y);
    fa[x]=y;
    if (dep[x]==dep[y]) dep[y]++;
    tim[x]=t;
}
int main()
{
    memset(fa,-1,sizeof(fa));
    scanf("%d",&n);m=n*n;
    for (int u=1;u<=n;u++)
        scanf("%s",ss[u]+1);
    bfs();
    for (int u=1;u<=n;u++)
    {
        for (int i=1;i<=n;i++)
        {
            /*printf("%d ",f[u][i]);
            printf("\n");*/
            if (f[u][i]>0)
                f[u][i]=(f[u][i]-1)*2+1;
        }
    }
    for (int u=1;u<=n;u++)
        for (int i=1;i<=n;i++)
            s[P(u,i)]=make_pair(f[u][i],make_pair(u,i));
    sort(s+1,s+1+m,cmp);
    for (int u=1;u<=m;u++)
    {
        int x=s[u].second.first,y=s[u].second.second,t=s[u].first;
        fa[P(x,y)]=P(x,y);
        if (x+1<=n&&fa[P(x+1,y)]!=-1) link(find_fa(P(x,y)),find_fa(P(x+1,y)),t);
        if (y+1<=n&&fa[P(x,y+1)]!=-1) link(find_fa(P(x,y)),find_fa(P(x,y+1)),t);
        if (y-1>=1&&fa[P(x,y-1)]!=-1) link(find_fa(P(x,y)),find_fa(P(x,y-1)),t);
        if (x-1>=1&&fa[P(x-1,y)]!=-1) link(find_fa(P(x,y)),find_fa(P(x-1,y)),t);
    }
    scanf("%d",&q);
    while (q--)
    {
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        int x=P(x1,y1),y=P(x2,y2);
        int now=x,now1=y;
        int depx=0,depy=0;
        while (fa[now]!=now) {depx++;now=fa[now];}
        while (fa[now1]!=now1) {depy++;now1=fa[now1];}
        if (now1!=now)
        {
            printf("0\n");
            continue;
        }
        int ans=m;
        while (x!=y)
        {
        //  printf("%d %d\n",x,y);
            if (depx>depy)
            {
                swap(depx,depy);
                swap(x,y);
            }
            ans=min(ans,tim[y]);
            depy--;
            y=fa[y];
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36797743/article/details/81353106