[FZOJ1554] 大逃亡 (escape.*)

描述 Description

给出数字 N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000), 代表有 N 个敌人分布一个 X 行 Y 列的矩阵上,矩形的行号从 0 到 X-1, 列号从 0 到 Y-1 再给出四个数字 x1,y1,x2,y2, 代表你要从点 (x1,y1) 移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少, 以及在这个前提下,你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d), 那么它们的距离为 | a-c|+|b-d|。

输入格式 InputFormat

第一行给出数字 N,X,Y.
第二行给出 x1,y1,x2,y2.
下面将有 N 行,给出 N 个敌人所在的坐标。

输出格式 OutputFormat

在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。

样例输入 SampleInput

2 5 6
0 0 4 0
2 1
2 3

样例输出 SampleOutput

2 14

来源 Source

2014-10-4 NOIP 模拟赛 by lwher


FZOJ 1554


代码 Code

先 floodfill 出所有点到离其最近的敌人的距离,然后二分答案,spfa 判断可行性。

貌似用了太多 STL 了不开 O2 的话有一定几率会 T 掉几个点~~(>_<)~~

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int inf=0x7fffffff/27.11;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
int i,j,t,n,m,l,r,k,z,y,x;
int a[1005][1005];
bool used[1005][1005];
deque < pair<int,int> > q;
deque < pair<pair<int,int>,int> > f;
int sx,sy,ex,ey,X,Y;
int ans,step;
inline void read(int &x)
{
    x=0;char ch=getchar();
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void floodfill()
{
    int i,j,t,tx,ty;
    while (!q.empty())
    {
        for (i=0;i<4;i++)
        {
            tx=q.front().first+dx[i];ty=q.front().second+dy[i];
            if (tx<0 || tx>=X || ty<0 || ty>=Y) continue;
            if (a[tx][ty]>a[q.front().first][q.front().second]+1)
            {
                a[tx][ty]=a[q.front().first][q.front().second]+1;
                if (!used[tx][ty])
                {
                    used[tx][ty]=true;
                    q.push_back(make_pair(tx,ty));
                }
            }
        }
        q.pop_front();
    }
}
inline bool can(int s)
{
    int i,j,t,tx,ty;
    while (!f.empty()) f.pop_front();
    memset(used,false,sizeof(used));
    f.push_back(make_pair(make_pair(sx,sy),0));used[sx][sy]=true;
    while (!f.empty())
    {
        for (i=0;i<4;i++)
        {
            tx=f.front().first.first+dx[i];ty=f.front().first.second+dy[i];
            if (tx==ex && ty==ey)
            {
                step=f.front().second+1;
                return true;
            }
            if (tx<0 || tx>=X || ty<0 || ty>=Y) continue;
            if (a[tx][ty]<s) continue;
            if (!used[tx][ty])
            {
                used[tx][ty]=true;
                f.push_back(make_pair(make_pair(tx,ty),f.front().second+1));
            }
        }
        f.pop_front();
    }
    return false;
}
int main()
{
    freopen("escape.in","r",stdin);
    freopen("escape.out","w",stdout);
    read(n);read(X);read(Y);
    read(sx);read(sy);read(ex);read(ey);
    for (i=0;i<X;i++) for (j=0;j<Y;j++) a[i][j]=inf;
    memset(used,false,sizeof(used));
    for (i=1;i<=n;i++) read(x),read(y),q.push_back(make_pair(x,y)),a[x][y]=0,used[x][y]=true;
    floodfill();
    l=0;r=min(a[sx][sy],a[ex][ey]);
    ans=step=0;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        if (can(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%d %d\n",ans,step);
    return 0;
}