• NYOJ----最少步数


    最少步数

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:4
    描述

    这有一个迷宫,有0~8行和0~8列:

     1,1,1,1,1,1,1,1,1
     1,0,0,1,0,0,1,0,1
     1,0,0,1,1,0,0,0,1
     1,0,1,0,1,1,0,1,1
     1,0,0,0,0,1,0,0,1
     1,1,0,1,0,1,0,0,1
     1,1,0,1,0,1,0,0,1
     1,1,0,1,0,0,0,0,1
     1,1,1,1,1,1,1,1,1

    0表示道路,1表示墙。

    现在输入一个道路的坐标作为起点,再如输入一个道路的坐标作为终点,问最少走几步才能从起点到达终点?

    (注:一步是指从一坐标点走到其上下左右相邻坐标点,如:从(3,1)到(4,1)。)

    输入
    第一行输入一个整数n(0<n<=100),表示有n组测试数据;
    随后n行,每行有四个整数a,b,c,d(0<=a,b,c,d<=8)分别表示起点的行、列,终点的行、列。
    输出
    输出最少走几步。
    样例输入
    2
    3 1  5 7
    3 1  6 7
    样例输出
    12
    11
    用dfs 或 bfs进行穷举
    (1)DFS
    #include <stdio.h>
    #include <string.h>
    #define INF 80
    
    int res,flag[9][9];
    int maze[9][9]={
     1,1,1,1,1,1,1,1,1,
     1,0,0,1,0,0,1,0,1,
     1,0,0,1,1,0,0,0,1,
     1,0,1,0,1,1,0,1,1,
     1,0,0,0,0,1,0,0,1,
     1,1,0,1,0,1,0,0,1,
     1,1,0,1,0,1,0,0,1,
     1,1,0,1,0,0,0,0,1,
     1,1,1,1,1,1,1,1,1	
    };
    
    void DFS(int si,int sj,int ei,int ej,int count){
    	if(si==ei && sj==ej){
    		if(count + 1 < res)
    			res = count+1;
    		return;
    	}
    	if(si<0 || si>8 || sj<0 || sj>8 || flag[si][sj] || maze[si][sj]) return;
    	flag[si][sj]=1;
    	// four corners
    	if((si==0 || si==8) && ((sj==0 || sj==8))){
    		int ssi,sssi,ssj,sssj;
    		if(si==0 && sj==0){
    			ssi=si+1,ssj=sj;
    			sssi=si,sssj=sj+1;
    		}
    		else if(si==0 && sj==8){
    			ssi=si+1,ssj=sj;
    			sssi=si-1,sssj=sj;
    		}
    		else if(si==8 && sj==0){
    			ssi=si-1,ssj=sj;
    			sssi=si,sssj=sj+1;
    		}
    		else{
    			ssi=si-1,ssj=sj;
    			sssi=si,sssj=sj-1;
    		}
    		DFS(ssi,ssj,ei,ej,count+1);
    		DFS(sssi,sssj,ei,ej,count+1);
    	}
    	//four edges
    	else if(!(si>0 && si<8 && sj>0 && sj<8)){
    		int ssi,ssj,sssi,sssj,ssssi,ssssj;
    		if(si==0){
    			ssi=si,ssj=sj-1;
    			sssi=si,sssj=sj+1;
    			ssssi=si+1,ssssj=sj;
    		}
    		else if(si==8){
    			ssi=si,ssj=sj-1;
    			sssi=si,sssj=sj+1;
    			ssssi=si-1,ssssj=sj;
    		}
    		else if(sj==0){
    			ssi=si,ssj=sj+1;
    			sssi=si-1,sssj=sj;
    			ssssi=si+1,ssssj=sj;
    		}
    		else{
    			ssi=si-1,ssj=sj;
    			sssi=si+1,sssj=sj;
    			ssssi=si,ssssj=sj-1;
    		}
    		DFS(ssi,ssj,ei,ej,count+1);
    		DFS(sssi,sssj,ei,ej,count+1);
    		DFS(ssssi,ssssj,ei,ej,count+1);
    	}
    	else{
    		DFS(si-1,sj,ei,ej,count+1);
    		DFS(si+1,sj,ei,ej,count+1);
    		DFS(si,sj-1,ei,ej,count+1);
    		DFS(si,sj+1,ei,ej,count+1);
    	}
    	flag[si][sj]=0;
    }
    
    int main(){
    	int n,si,sj,ei,ej;
    	scanf("%d",&n);
    	while(n--){
    		scanf("%d%d%d%d",&si,&sj,&ei,&ej);
    		res = INF;
    		memset(flag,0,sizeof(flag)); 
    		DFS(si,sj,ei,ej,-1); 
    		printf("%d
    ",res); 
    	}
    	return 0;
    } 
    

     (2)BFS

    bfs求最小步数之所以不用更新距离d,是因为访问任何一个点(i,j)
    必然都是距离(si,sj)最短距离(联想起bfs的分支图即明白这一点)

    #include <iostream>
    #include <cstdio>
    #include <queue>
    
    using namespace std;
    
    typedef pair<int,int> P; //用结构体struct point{x,y}亦可 
    const int INF=80;
    
    char maze[10][10]={ //用char更节约内存 
     "111111111",
     "100100101",
     "100110001",
     "101011011",
     "100001001",
     "110101001",
     "110101001",
     "110100001",
     "111111111"
    };
    int sx,sy,gx,gy;
    int d[9][9]; //出发点到(i,j)的最短路径,同时起到判断是否已访问的作用 
    int dis[4][2]={ //or 定义dx[4]&dy[4]
    	1,0,
    	0,1,
    	-1,0,
    	0,-1	 
    };
    
    void Init(){
    	int i,j;
    	for(i=0;i<9;i++)
    		for(j=0;j<9;j++)
    			d[i][j]=INF;
    } 
    
    void BFS(){
    	queue <P> q;
    	q.push(P(sx,sy));
    	d[sx][sy]=0;
    	while(q.size()){ //or !q.empty():仍有点未被访问 
    		P p=q.front();
    		q.pop();
    		if(p.first==gx && p.second==gy) 
    			break;
    		int i=0;
    		for(;i<4;i++){
    			int x=p.first+dis[i][0],y=p.second+dis[i][1];
    			if(x>=0 && x<=8 && y>=0 && y<=8 
    				&& maze[x][y]=='0' 
    				&& d[x][y]==INF){ //表示(x,y)暂未访问 
    				d[x][y]=d[p.first][p.second]+1;
    				q.push(P(x,y));
    			}
    		}
    	}
    	printf("%d
    ",d[gx][gy]);
    }
    
    int main(){
    	int n;
    	scanf("%d",&n);
    	while(n--){
    		scanf("%d%d%d%d",&sx,&sy,&gx,&gy);
    		Init();
    		BFS();
    	}
    	return 0;
    }
    

    对BFS的一点补充。。。

    我们实际可以不用定义点,只要能够对不同的点进行区分即可,用9*i+j可将二维的点转化为一维(实际有点时间换空间的意味,全当另一种方法的了解),核心如下:

    int graph[81],front,rear;front和rear共同起到队列的作用,入队,graph[rear++]=9*i+j(入队点为(i,j)),出队时,x=graph[front]/9,y=graph[front++]%9;

    其余同BFS代码

    其中,bfs的代码参照:http://blog.csdn.net/sevenmit/article/details/13168363

  • 相关阅读:
    【Css】SCSS基本语法
    【Css】Scss 与 Sass 简单示例
    【移动端】cordova在app中打开外部链接——cordova-plugin-inappbrowser
    border-radius圆角边框属性讲解
    css 设置 transform 无效
    linux下设置php执行命令
    linux下php命令无法使用如何解决
    微信小程序 --- 表单输入验证(手机号、邮箱验证、输入非空)
    微信小程序倒计时组件开发
    小程序--三级联动
  • 原文地址:https://www.cnblogs.com/emptyCoder/p/6498922.html
Copyright © 2020-2023  润新知