Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6937 | Accepted: 4056 |
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, };
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
(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; }
经典递归问题--走迷宫--POJ 3984,布布扣,bubuko.com
原文:http://blog.csdn.net/linsheng9731/article/details/23439815