经典递归问题--走迷宫--POJ 3984

34 篇文章 0 订阅
28 篇文章 0 订阅

迷宫问题

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 6937 Accepted: 4056

Description

定义一个二维数组:
int maze[5][5] = {

	0, 1, 0, 0, 0,

	0, 1, 0, 1, 0,

	0, 0, 0, 0, 0,

	0, 1, 1, 1, 0,

	0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

递归算法在许多搜索最优解的问题当中经常出现,因为一开始问题的规模总是很大用一般的枚举法,模拟法都不能很好的解决。而这时候我们通常会采用分治+递归的方法去求解。先把问题的规模一步步减小,找到最小规模的解后最逐步回朔还原总的解。但是有一点我们要注意的,递归的效率很低,如果不做优化相当于暴力求解。优化的方法就是仔细剖析问题在分解过程中一些重复的或者无用的过程,并且把他们排除在外以达到节省时间的目的。

例如上面这个走迷宫的问题,我们先把问题分解。每次我们做选择会碰到四种情况,即向右,向左,向下,向上。如果下一个位置可以走,那么把原来的位置标记为已经走过,并走到下一个位置。这时候问题有变成从4个方向里选一个,这时候我们可以得出问题的递归部分。问题出口在哪里,很明显当我们走到(4,4)位置的时候我们就认为求解完成。

接下来就是优化的问题,一方面是缩短时间,一方面是保证这条路是最短的。因为入口和出口是固定的所以我们优先走右下两个方向,最优解一定在这两个方向里面。

 

下面是代码:

// 迷宫问题.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<stdio.h>
#include<stack>
using namespace std;
stack<int> s1,s2;
int a[5][5]={0};

bool dfs(int i,int j)
{
	if(i==4&&j==4)
	{
		s1.push(i);
		s2.push(j);
		return true;
	}
		
	if(i>=0&&i<=4&&j>=0&&j<=4)
	{
		if(a[i][j]==0)
		{
			a[i][j]=1;
			if(dfs(i,j+1)||dfs(i+1,j)||dfs(i,j-1)||dfs(i-1,j))//有顺序的 先右下 再左上
			{
				//printf("%d  %d\n",i,j);
				s1.push(i);
				s2.push(j);
				return true;
			}
			else
			{
				a[i][j]=0;
				return false;
			}
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}

void print()
{
	while(!s1.empty())
	{
		printf("(%d, %d)\n",s1.top(),s2.top());
		s1.pop();
		s2.pop();
	}

}


int main()
{ 
	int temp=0;
	while(scanf("%d",&temp)!=EOF)
	{
		a[0][0]=temp;
		for(int i=0;i<5;i++)
			for(int j=0;j<5;j++)
			{ 
				if(i==0&&j==0) continue;
				scanf("%d",&a[i][j]);
			}
			dfs(0,0);
			print();

	}
	return 0;
}


 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值