• 【洛谷P2199】最后的迷宫【BFS】【DFS】


    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P2199
    给出一个图及起点和终点,只要到达终点所在行、列或对角线上且两点之间没有墙就算到达终点。求到达终点的最少步数。


    思路:

    这道题真的算是蓝题吗。。。
    算是很裸的广搜了。
    这道题和裸的广搜其实只有一个差别:只要到达终点所在行、列或对角线上且两点之间没有墙就算到达终点。也就是说,这道题有多个终点,到达任意一个即可。
    那么就直接跑一边DFS,从原终点往8个方向跑,直到遇见墙为止。那么走到的点就都是成立的终点。
    之后就从起点跑BFS。就完全是裸的了。
    还有这道题说100%100\%的数据范围是n×m16384n\times m\leq 16384,所以如果是最坏情况就会有n=1,m=16384n=1,m=16384,那么开二维数组就会炸内存。所以要把二维数组压成一个一位数组。
    有多组数据,所以时间复杂度为O(tnm)O(tnm)


    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int dx[]={0,1,-1,0,0,-1,-1,1,1};
    const int dy[]={0,0,0,1,-1,-1,1,-1,1};
    int n,m,sx,sy,tx,ty,head,tail,ans[20501],state[20501];
    bool a[20501],map[20501],p[20501];
    char c;
    
    void dfs(int x,int y,int k)  //找终点
    {
    	if (map[(x-1)*m+y]==1) return;  //墙
    	if (x<1||x>n||y<1||y>m) return;  //越界
    	a[(x-1)*m+y]=1;  //标记为终点
    	dfs(x+dx[k],y+dy[k],k);
    }
    
    void bfs()  //裸的广搜
    {
    	head=0;
    	tail=1;
    	state[1]=(sx-1)*m+sy;
    	while (head<tail)
    	{
    		head++;
    		for (int i=1;i<=4;i++)
    		{
    			tail++;
    			int x=(state[head]-1)/m+1;  
    			int y=state[head]-(x-1)*m;  //取出行和列
    			x+=dx[i];
    			y+=dy[i];  //移动
    			if (x<1||x>n||y<1||y>m)  //越界
    			{
    				tail--;
    				continue;
    			}
    			state[tail]=(x-1)*m+y;  //入队
    			if (p[state[tail]]||map[state[tail]])   //来到过这个点或是墙
    			{
    				tail--;
    				continue;
    			}
    			p[state[tail]]=1;
    			ans[tail]=ans[head]+1;
    			if (a[state[tail]])  //到达任意一个终点
    			{
    				printf("%d\n",ans[tail]);
    				return;
    			}
    		}
    	}
    	printf("Poor Harry\n");  //无法到达
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	 for (int j=1;j<=m;j++)
    	 {
    		cin>>c;
    		while (c=='\n'||c==' ') cin>>c;
    		if (c=='X') map[(i-1)*m+j]=1;
    	 } 
    	while (1)
    	{
    		scanf("%d%d%d%d",&tx,&ty,&sx,&sy);
    		if (!tx&&!ty&&!sx&&!sy) break;
    		memset(a,0,sizeof(a));
    		memset(ans,0,sizeof(ans));
    		memset(p,0,sizeof(p));
    		a[(tx-1)*m+ty]=1;
    		for (int i=1;i<=8;i++)
    		 dfs(tx,ty,i);
    		if (a[(sx-1)*n+sy])   //特判,本来就在终点上
    		{
    			printf("0\n");
    			continue;
    		}
    		bfs();
    	}
    	return 0;
    }
    
  • 相关阅读:
    [贪心] Jzoj P4249 游戏
    [数学][快速幂] Jzoj P4248 n染色
    [dfs] Jzoj P4252 QYQ的图
    [折半搜索][has] Jzoj P4250 路径
    [计数dp][数学] Jzoj P4254 集体照
    [Tarjan][并查集][dp] Jzoj P4253 QYQ在艾泽拉斯
    [支配树][lca][倍增][线段树][拓扑] Jzoj P4240 游行
    [贪心] Jzoj P4244 yi
    [数位dp] Jzoj P4239 光棍
    [扫描线][差分约束] Jzoj P4238 纪念碑
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998602.html
Copyright © 2020-2023  润新知