模拟赛 大逃亡(时间限制:1s;空间限制:128MB)

题目描述

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

题解

搜索+二分判定,考试时脑子秀逗了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int n,xs,ys,xe,ye,X,Y;
struct diren{int x,y;} d[10002],q[1000002];
int map[1002][1002],ct[1002][1002],minl,ans;
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
void init()
{
	scanf("%d%d%d",&n,&X,&Y);
	scanf("%d%d%d%d",&xs,&ys,&xe,&ye);
	int i;
	for(i=1;i<=n;i++) scanf("%d%d",&d[i].x,&d[i].y);
}
void pre()
{
	int i,t=0,w=0,xn,yn,xt,yt;
	memset(map,-1,sizeof(map));
	for(i=1;i<=n;i++)
	   {q[w].x=d[i].x; q[w].y=d[i].y; w++;
	    map[d[i].x][d[i].y]=0;
	   }
	while(t<w)
	   {xn=q[t].x; yn=q[t].y; t++;
	    for(i=0;i<4;i++)
	       {xt=xn+xx[i]; yt=yn+yy[i];
		    if(xt<0||xt>=X||yt<0||yt>=Y||map[xt][yt]!=-1) continue;
		    map[xt][yt]=map[xn][yn]+1;
		    q[w].x=xt; q[w].y=yt; w++;
		   }
	   }
}
bool check(int x,int y,int jl)
{
	if(x<0||x>=X||y<0||y>=Y||map[x][y]<jl) return false;
	if(ct[x][y]!=-1) return false;
	return true;
}
bool find(int jl)
{ 
	int t=0,w=1,i,xn,yn,xt,yt;
	//if(map[xs][ys]<jl) return false;
	memset(ct,-1,sizeof(ct));
	q[t].x=xs; q[t].y=ys; ct[xs][ys]=0;
	while(t<w)
	   {xn=q[t].x; yn=q[t].y; t++;
	    for(i=0;i<4;i++)
	       {xt=xn+xx[i]; yt=yn+yy[i];
		    if(!check(xt,yt,jl)) continue;
		    ct[xt][yt]=ct[xn][yn]+1;
		    if(xt==xe&&yt==ye) {minl=jl; ans=ct[xt][yt]; return true;}
			q[w].x=xt; q[w].y=yt; w++;
		   }
	   }
	return false;
}
void work()
{
	pre();
	int l=0,r=map[xs][ys],mid;
	while(l<=r)
	   {mid=(l+r)>>1;
	    if(find(mid)) l=mid+1;
		else r=mid-1; 
	   }
	printf("%d %d\n",minl,ans);
}
int main()
{
	freopen("escape.in","r",stdin);
	freopen("escape.out","w",stdout);
	init(); work();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值