[DFS]迷宫最小步数

描述

这有一个迷宫,有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
   #include <stdio.h>
  int step,x,y,ex,ey;
  bool vis[9][9],map[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 i,int j,int cnt)
  {
      if(i<0||i>8||j<0||j>8||vis[i][j]||map[i][j]||cnt>=step)
                return;
      if(i==ex&&j==ey)
      {
          step=cnt;     //到达终点
          return;
      }
  
      vis[i][j]=1;       // 这个已经走过了
  
     dfs(i,j-1,cnt+1);    //左  ,每走一步,cnt+1
     dfs(i-1,j,cnt+1);    //上
     dfs(i,j+1,cnt+1);    //右
     dfs(i+1,j,cnt+1);    //下
 
     vis[i][j]=0;
  }
  
  int main()
   {
      int n;
      scanf("%d",&n);
      while(n--)
      {
          scanf("%d%d%d%d",&x,&y,&ex,&ey);
          step=100;
          dfs(x,y,0);                //初始化0
          printf("%d\n",step);
      }
      return 0;
  }
 

相关1:题目不变,问有多少种走法。

#include <stdio.h>
int a[8][8];	//既是图形数组也是标记数组 
int count;
int m,n;
void dfs(int i,int j)
{
	if(i == n-1 && j == m-1)	//出口,到达终点 
	{
		count ++ ;
		return ;
	}
	a[i][j] = 1; //标记 
	if(i > 0 && !a[i - 1][j])       dfs(i - 1,j); 	//向上移动(条件:a[i][j]能向上通过并且为被标记,以下同理) 
	if(i < n - 1 && !a[i + 1][j])   dfs(i + 1,j); 	//下 
	if(j > 0 && !a[i][j - 1])       dfs(i,j - 1);	//左 
	if(j < m - 1 && !a[i][j + 1])   dfs(i,j + 1);	//右 
	a[i][j] = 0;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		int i,j;
		count = 0;
		scanf("%d%d",&n,&m);
		for(i = 0;i < n;i ++ )
			for(j = 0;j < m;j ++ )
				scanf("%d",&a[i][j]);	
		dfs(0,0);	
		printf("%d\n",count);
	}
	return 0;
}

相关2:题目变动为可以朝八个方向走,问有多少种走法?

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int sx[8]={0,0,1,1,1,-1,-1,-1};//八个方向,初始化赋好值
int sy[8]={1,-1,0,1,-1,0,1,-1};
int n,i,j,ans=0;
int a[100][100],b[100][100];
 
void dfs(int s,int t)
{
	int i,x,y;
	if (s==1&&t==n)//如果到达终点,方案数+1
	{
		ans++;
		return;
	}
	for (i=0;i<8;++i)//枚举八个方向
	{
		x=s+sx[i];
		y=t+sy[i];
		if (x>0&&y>0&&x<=n&&y<=n&&a[x][y]==0&&b[x][y]==0)//前四个条件是判断是否越界,最后一个是判断是否访问
		{                                                //过
			b[x][y]=1;
			dfs(x,y);
			b[x][y]=0;
		}
	}
	return;
}
int main()
{
	scanf("%d",&n);
	for (i=1;i<=n;++i)
	  for (j=1;j<=n;++j)
	    scanf("%d",&a[i][j]);
	b[1][1]=1;      //b[i][j]表示坐标为(i,j)这个点有没有被访问过
	dfs(1,1);
	printf("%d",ans);
	return 0;
}

  

相关3:有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回一共有多少种不同的走法。 

for(int i = 0; i <= m; i++) {
            dp[i][0] = 1;
        }
        for(int i = 0; i <= n; i++) {
            dp[0][i] = 1;
        }
        for(int i = 1; i <= m; i++) {
            for(int j = 1; j <= n; j++) {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        cout<<dp[m][n];

  

 

 

 

 

 

 

 

 

 

 

posted @ 2017-03-28 18:00  道微真理  阅读(674)  评论(0)    收藏  举报