黄学长模拟day1 大逃亡

给出数字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|。

输入:

第一行给出数字N,X,Y

第二行给出x1,y1,x2,y2

下面将有N行,给出N个敌人所在的坐标

输出:

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

Sample input

2 5 6

0 0 4 0

2 1

2 3

Sample output

2 14

/*
同bzoj热身赛,二维前缀和,灌水留坑
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn = 10050,inf = 987654;
inline int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
    return x*f;
}
struct nd{
    int x;
    int y;
};
int p,n,m;
int ex[maxn],ey[maxn],xa,xb,ya,yb;
int flag,dis[1150][1150],vis[1050][1050];
short d[3100][3100],s[3100][3100];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
bool emy[3050][3050];
inline bool jud(int x,int y,int t){
    if(x < 0 || y < 0 || x >= m || y >= n) return false;
    if(t == 0) return true;
    t--;
    int tx=1005+x-y+t,ty=x+y+t,dx=1005+x-y-t,dy=x+y-t;
    if(ty>=n+m-1) ty = n+m-2;       
    if(tx>=1005+m) tx = 1004+m;
    int tot = s[ty][tx];
    if(dy>0&&dx>1006-n) tot += s[dy-1][dx-1];
    if(dy>0) tot -= s[dy-1][tx];
    if(dx>1006-n) tot -= s[ty][dx-1];
    if(tot) return false;
    else return true;
}
bool check(int t){
    if(!jud(xa,ya,t)) return false;
    flag++;
    for(int i = 0;i <= n+10;i++){
        for(int j = 0;j <= m+10;j++){
            dis[i][j] = inf;
        }
    }
    nd now,nxt;
    now.x = xa;
    now.y = ya;
    queue<nd> q;
    q.push(now);
    dis[ya][xa] = 0;
    vis[ya][xa] = flag;
    while(!q.empty()){
        now = q.front();
        q.pop();
        //cout<<now.y<<" "<<now.x<<endl;
        for(int dr = 0;dr < 4;dr++){
            nxt.x = now.x + dx[dr];
            nxt.y = now.y + dy[dr];
            if(jud(nxt.x,nxt.y,t)&&vis[nxt.y][nxt.x] != flag){
                dis[nxt.y][nxt.x] = dis[now.y][now.x] + 1;
                vis[nxt.y][nxt.x] = flag;
                q.push(nxt);
                if(nxt.y == yb && nxt.x == xb) return true;
            }
        }
    }
    return false;
}
int main(){
    freopen("escape.in","r",stdin);
    freopen("escape.out","w",stdout);
    cin>>p>>m>>n>>xa>>ya>>xb>>yb;
    for(int i = 1;i <= p;i++){
        scanf("%d%d",&ex[i],&ey[i]);
        emy[ex[i]+ey[i]][1005+ex[i]-ey[i]] = true;
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(emy[i][j]) d[i][j] = d[i][j-1] + 1;
            else d[i][j] = d[i][j-1];
        }
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(!i) s[i][j] = d[i][j];
            else s[i][j] = s[i-1][j] + d[i][j];
        }
    }
    int l = 0,r = n + m,mid,ans1,ans2;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid)){
            ans1 = mid;
            ans2 = dis[yb][xb];
            l = mid + 1;
        }else{
            r = mid - 1;
        }
    }
    cout<<ans1<<" "<<ans2;
    return 0;
}

 

posted @ 2016-10-23 20:35  ACforever  阅读(225)  评论(0编辑  收藏  举报