• 【题解】[Nwerc 2006]escape -C++


    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|。
    Input
    第一行给出数字N,X,Y
    第二行给出x1,y1,x2,y2
    下面将有N行,给出N个敌人所在的坐标
    Output
    在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
    Sample Input

    2 5 6
    0 0 4 0
    2 1
    2 3
    

    Sample Output

    2 14
    

    这周考试的第三题...
    看起来很水但是做起来会发现没有思路
    肯定要先构造一个原图(这个不用说)
    我想的是用best[i][j]来表示点(i,j)距离最近的敌人的距离。
    但是我发现我只会用(O(n*x*y))的时间复杂度预处理!!!
    这个思路很简单,best数组初始值极大值,每次输入一对坐标就遍历一遍这个图,把best[i][j]和敌人与点(i,j)的距离取min,然后就可以得到一张预处理过的图。
    很明显,这玩意会炸:(N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000))
    (O(n*x*y))原地爆炸好吗!!!
    经过机房大佬细心开导 ,预处理用一个BFS来完成。
    思路:输入坐标打入队列,然后和正常的BFS一样向周围扩散求得best值,因为BFS先遇到的肯定最优,所以这个方法只需要大概(O(x*y))的时间复杂度就能完成预处理。
    然后就是搜索过程emmm
    搜索需要用二分来完成!!!!
    这道题类似的,把最终值拿来二分,下界0,上界是终点和起点的best值取min!因为起点和终点是一定会经过的,不妨用这个特性来缩小二分范围,然后用mid传入bfs搜索一波就行...具体二分过程不多讲解,不懂的可以看一下代码:

    #include<bits/stdc++.h>
    #define FAST_IN std::ios::sync_with_stdio(false);cin.tie(NULL);
    using namespace std;
    int x,y,n,sx,sy,ex,ey,step;
    inline int hl/*howlong*/(int a,int b,int c,int d)
    {
    	return abs(a-c)+abs(b-d);
    }
    struct node
    { 
    	int x,y,t;
    };
    int best[1010][1010];
    bool vis[1010][1010];
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    queue<node> s;
    void bfs1()
    {
        while(!s.empty())
        {
            node now=s.front();
            s.pop();
            for(int i=0;i<4;i++)
            {
                int tx=now.x+dir[i][0];
                int ty=now.y+dir[i][1];
                if(tx>=0&&ty>=0&&tx<x&&ty<y&&!best[tx][ty])
                {
                    best[tx][ty]=now.t+1;
                    s.push((node){tx,ty,now.t+1});
                }
            }
        }
    }
    bool bfs(int left)
    {
    	if(best[sx][sy]-1<left)return 0;
    	memset(vis,0,sizeof(vis));
    	queue<node> q;
    	q.push((node){sx,sy,0});
    	vis[sx][sy]=1;
    	while(!q.empty())
    	{
    		node now=q.front();
    		q.pop();
    		if(now.x==ex&&now.y==ey)
    		{
    			step=now.t;
    			return 1;
    		}
    		for(int i=0;i<4;i++)
    		{
    			int tx=now.x+dir[i][0],ty=now.y+dir[i][1];
    			if(best[tx][ty]-1<left)continue;
    			if(!vis[tx][ty]&&best[tx][ty]-1>=left&&0<=tx&&tx<x&&0<=ty&&ty<y)
    			{
    				q.push((node){tx,ty,now.t+1});
    				vis[tx][ty]=1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	FAST_IN;
    	scanf("%d%d%d%d%d%d%d",&n,&x,&y,&sx,&sy,&ex,&ey);
    	for(int i=1;i<=n;i++)
    	{
    		int tx,ty;
    		scanf("%d%d",&tx,&ty);
    		best[tx][ty]=1;
    		s.push((node){tx,ty,1});
    	}
    	bfs1();
    //	for(int i=0;i<x;i++)
    //	{
    //		for(int j=0;j<y;j++)
    //		{
    //			cout<<best[i][j];
    //		}
    //		cout<<endl;
    //	}
    	int l=0,r=best[ex][ey];
    	while(l<r)
    	{
    		int mid=(l+r)/2;
    		if(bfs(mid))l=mid+1;
    		else r=mid;
    	}
    	cout<<r-1<<" "<<step<<endl;
    	return 0;
    }
    

    ov.

    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    js例子
    js表单验证
    Python之Numpy的基础及进阶函数(图文)
    Numpy库的下载及安装(吐血总结)
    世界,你好!
    用逻辑回归模型解决互联网金融信用风险问题
    用逻辑回归模型解决互联网金融信用风险问题
    如何建立投资模型
    如何建立投资模型
    秒懂数据类型的真谛—Python基础前传(4)
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11225759.html
Copyright © 2020-2023  润新知