1 .Preface

/**

* There have been many data to introduce the algorithm. So I will try to simply explain it and explain the program in detail.

*/

/**

* Prerequisites:

*  1). a survival skill in CPP programing language.

*  2). a curious mind for maze problem.

*

*/

//Image this, you have maze, just as following:

/*

*

*     1  1  1  1  1  1  1  1  1  1

*-> 1  0  0  1  0  0  0  1  0  1

*     1  0  0  1  0  0  0  1  0  1

*     1  0  0  0  0  1  1  0  0  1

*     1  0  1  1  1  0  0  0  0  1

*     1  0  0  0  1  0  0  0  0  1

*     1  0  1  0  0  0  1  0  0  1

*     1  0  1  1  1  0  1  1  0  1

*     1  1  0  0  0  0  0  0  0  1  -->exit

*     1  1  1  1  1  1  1  1  1  1 

*/

//the entrance is [1,1], and exit is [8,8].

//How could you find a valid way to get through this?

/*

* when  start with [1, 1] , we will arrive some special position, which provide us many paths .For example, if we reside in [1, 1], there have two paths for us, [ 2, 1] and [ 1, 2]. Those speical nodes connect each other and compose a complexity topology network.



*

* To solve this problem, we could do as following:

*  step 1: just go ahead as one pleases , but record all nodes which has arrived.

*  step 2: if arrive a dead end, that mean you was choose a wrong path. So you need to go back the same way, find the last node which you did a choice, and  step into another choice.

*  step 3: Then repeat step 1 untill arrive the exit.

*

*/

2.Source code

/**

* Now, check this source code. I divided this problem with three parts: a stack, a map, and a boy who provide solve solution. First, let us put that poor little boy into this maze.( brutally )

*/

2. 1 Tool--stack.h

/**

* To traverse the network totally, the little boy must ensure he can go back the same way. So he save all of nodes,which he has been arrived,into a stack. The feature of stack is

* first in, first out. That's what we lack.

*/

/**
* For make this stack more useful, a class template is created.
*/
#ifndef STACK_H
#define STACK_H typedef int INDEX; template < class ELEM>
class STACK{
public:
STACK( int capacity); //capacity
~STACK( void);
/*
* some basic operation function.
*/
bool pop( ELEM &item);
bool push( ELEM item);
/*
* sometimes, we want to visit those elements in the stack simply, instead of
* pop them from stack.
*/
bool reset_v( void); //reset view point
bool pop_v( ELEM &item); //view stack private:
/*
* the bottom of stack
*/
ELEM *base;
/*
* the top of stack.
*/
INDEX top;
/*
* the current position for pop
*/
INDEX cur;
/*
* the current postion for visit stack
*/
INDEX v_cur;
}; #define STACK_MAX 1000 /**
* This is just a simply stack, and even don't consider dynamic extension.
*/
template <class ELEM>
STACK<ELEM>::STACK(int capacity)
{
if( ( capacity<=0)
||( capacity>STACK_MAX))
{
this->base = NULL;
return ;
}
this->base = NULL;
this->base = new ELEM[capacity];
this->top = capacity -1;
this->cur = -1;
this->v_cur = -1;
} template <class ELEM>
STACK<ELEM>::~STACK( void)
{
if( NULL!=this->base)
{
delete [](this->base);
this->base = NULL;
}
} template <class ELEM>
bool STACK<ELEM>::push( ELEM item)
{
if( (NULL==this->base)
||(this->top==this->cur))
return false; this->cur ++;
this->base[this->cur] = item;
return true;
} template <class ELEM>
bool STACK<ELEM>::pop( ELEM &item)
{
if( (NULL==this->base)
||(this->cur<0))
return false; item = this->base[this->cur];
this->cur--; return true;
} /**
* This function is used to visit stack.
*/
template <class ELEM>
bool STACK<ELEM>::pop_v( ELEM &item)
{
if( (NULL==this->base)
||(this->v_cur<0))
return false; item = this->base[this->v_cur];
this->v_cur--; return true;
} /**
* reset the posion of visit at current postion of stack.
* That is necessary before use pop_v().
*/
template <class ELEM>
bool STACK<ELEM>::reset_v( void)
{
this->v_cur = this->cur;
return true;
} #endif

2.2 Tool--map.h

/**

* Obviously, a map is necessary. By the help of the map, the boy could  concentrate on hisself's work rather than be busy with some things about map. That make the code is more clear and simple.

*/

/**
* Map is a 2D matrix. For a element in the matrix, it compose by three parts:
* X coordinate, Y coordinate and additional data in which we could save some
* attribute information about this node.
*/
#ifndef MAP_H
#define MAP_H #define MAP_MAX 15 typedef int COORDINATE; template <class NODE>
class MAP{
public:
MAP( int width);
~MAP( void);
/*
* get a node which reside in [x,y]. The information of node
* will be write into @nod.
*/
bool cur( COORDINATE x, COORDINATE y , NODE &nod);
/*
* get a node reside in [ x-1, y].
*/
bool left( COORDINATE x, COORDINATE y , NODE &nod);
bool right( COORDINATE x, COORDINATE y, NODE &nod);
bool up( COORDINATE x, COORDINATE y, NODE &nod);
bool down( COORDINATE x, COORDINATE y, NODE &nod);
/*
* set a map node
*/
bool set( COORDINATE x, COORDINATE y, NODE &nod); private:
/*
* point to the map
*/
NODE **p;
int wid;
}; /**
* Init the size of map. Because we don't know any thing about the size,
* nither width, nor height. So we use a trick.
*/
template <class NODE>
MAP<NODE>::MAP( int width)
{
if( width>MAP_MAX)
{
this->p = NULL;
return;
}
this->p = NULL;
#if 0
this->p = ( NODE **)malloc( sizeof(NODE)*width*width);
#else
this->p = new NODE*[width];
for( int i=0; i<width; i++)
this->p[i] = new NODE[width];
#endif
this->wid = width;
} template <class NODE>
MAP<NODE>::~MAP( void)
{
if( NULL!=this->p)
{
#if 0
free (this->p);
#else
for( int i=0; i<this->wid; i++)
delete []this->p[i];
delete []this->p;
#endif
this->p = NULL;
this->wid = 0;
}
} template <class NODE>
bool MAP<NODE>::cur(COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<0||x>=this->wid)
||(y<0||y>=this->wid))
return false; nod = this->p[x][y];
return true;
} template <class NODE >
bool MAP<NODE >::left( COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<0||x>=this->wid)
||(y<=0||y>=this->wid))
return false; nod = this->p[ x][y-1];
return true;
} template <class NODE>
bool MAP<NODE>::right( COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<0||x>=this->wid)
||(y<0||y>=this->wid-1))
return false; nod = this->p[x][y+1];
return true;
} template <class NODE>
bool MAP<NODE>::up( COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<=0||x>=this->wid)
||(y<0||y>=this->wid))
return false; nod = this->p[x-1][y];
return true;
} template <class NODE>
bool MAP<NODE>::down( COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<0||x>=this->wid-1)
||(y<0||y>=this->wid))
return false; nod = this->p[x+1][y];
return true;
} template <class NODE>
bool MAP<NODE>::set( COORDINATE x, COORDINATE y, NODE &nod)
{
if( (x<0||x>=this->wid)
||(y<0||y>=this->wid))
return false; if( NULL==this->p)
{
return false;
} this->p[x][y] = nod;
return true;
} #endif

2.3 Operator--boy

#include <stdio.h>
#include <iostream> /**
* To traverse the network totally, the little boy must ensure he can go back the same way.
* So he save all of nodes,which he has been arrived,into a stack. The feature of stack is
* first in, first out. That's what we lack.
*/
#include "../stack.h" /**
* Obviously, a map is necessary. By the help of the map, the boy could
* concentrate on hisself's work rather than be busy with some things about map.
* That make the code is more clear and simple.
*/
#include "map.h" //map node
typedef unsigned char UINT8; #define MAP_WID 10
#define END_X (MAP_WID-2) //8
#define END_Y (MAP_WID-2) //8 #define STACK_DEPTH 200 enum ORIEN{
O_RIGHT,
O_DOWN,
O_LEFT,
O_UP,
O_INVIALID,
O_MAX,
}; enum TERRAIN {
T_NOR = 0,
T_BLOCK = 1,
T_INVALID = 2,
}; /**
* map information, 1 meaning for T_BLOCK. 0 meaning for T_NOR.
*/
static int map_v[MAP_WID][MAP_WID] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1,
1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
1, 0, 1, 1, 1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 1, 0, 0, 0, 1, 0, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1, 0, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
}; /*
* basic element in map was used to record all information about
* a node.
*/
typedef struct {
COORDINATE x;
COORDINATE y;
TERRAIN val;
ORIEN orien;
bool hasComing;
} ELEMENT; /**
* And this is that poor boy. He will provide a algorithm to solve
* this maze problem. Of course, he need some tools: stack and
* map.
*/
class BOY {
public:
BOY( void);
~BOY( void);
/*
* begin to traverse this maze.
*/
bool work( void);
/*
* show information
*/
bool ShowMap( void);
bool ShowStack( void); private:
/*
* two important functions, they compose the core of this algorithm.
*/
bool forward( void);
bool backward( void);
/*
* work for those function above.
*/
bool hasNBranch( ELEMENT &c_elem, ELEMENT &nod, ORIEN &from); //has a new branch
bool isEnd( void); //arrive the end
bool findVisible( ELEMENT &c_elem, ELEMENT &nod, ORIEN& from);
bool wasCome( ELEMENT &c_elem); /*
* tool 1
*/
MAP<ELEMENT> map;
/*
* tool 2
*/
STACK<ELEMENT> stack;
/*
* current position
*/
ELEMENT cur;
}; BOY::BOY(void):map(MAP_WID), stack(STACK_DEPTH)
{
cur.x = 1;
cur.y = 1;
cur.val = T_NOR;
cur.orien = O_INVIALID; ELEMENT tmp_elem;
COORDINATE i,j;
for( i=0; i<MAP_WID; i++)
for( j=0; j<MAP_WID; j++)
{
tmp_elem.x = i;
tmp_elem.y = j;
tmp_elem.orien = O_INVIALID;
tmp_elem.hasComing = false;
tmp_elem.val = ( TERRAIN)map_v[i][j];
this->map.set( tmp_elem.x, tmp_elem.y, tmp_elem);
}
} BOY::~BOY( void)
{} bool BOY::work(void)
{
bool isContinue = true;
while( isContinue)
{
printf("this->cur[ %d, %d]\n", this->cur.x, this->cur.y);
/*
* go ahead until encounter a dead end or arrive the exit.
*/
while( this->forward( ))
{
printf("this->cur[ %d, %d]\n", this->cur.x, this->cur.y);
if( this->isEnd( ) )
return true;
}
/*
* when the boy has encounter a dead end, he need to backtrack.
* find a valid path.
*/
printf("back>\n");
isContinue=this->backward( );
} return false;
} /**
* based on current position, try to forward a step. If success, the previous postion
* will be push in the stack. and update the information of past node as arrived.
* if fail, that meaning current node is a dead end.
*/
bool BOY::forward(void)
{
ELEMENT tmp_elem;
ORIEN tmp_from = O_RIGHT; if( !this->hasNBranch( this->cur, tmp_elem, tmp_from))
{
return false;
}
this->cur.orien = tmp_from;
this->stack.push( this->cur); this->cur = tmp_elem;
this->cur.hasComing = true;
this->map.set( this->cur.x, this->cur.y, this->cur); return true;
} /**
* one of the core function. when the boy arrived a dead end,
* this function will be call . It go back the same way untill find
* a valid node that could give the little boy a new path(or a branch).
*/
bool BOY::backward(void)
{
ELEMENT tmp_elem;
ORIEN tmp_from = O_RIGHT;
while( this->stack.pop( tmp_elem))
{
this->cur = tmp_elem;
if( this->hasNBranch( this->cur, tmp_elem, tmp_from))
{
return true;
}
} return false;
} /**
* check whether @c_elem node has a valid path that deserve to visit.
* as same as other function, all information will be write into @elem
* and @from.
*/
bool BOY::hasNBranch( ELEMENT &c_elem, ELEMENT &elem, ORIEN &from)
{
ELEMENT tmp_elem;
ORIEN tmp_from = from;
while(1)
{
//find next visible position.
//Y:continue
//N:this node is a ending
if( !this->findVisible( c_elem, tmp_elem, tmp_from))
{
return false;
}
//was coming? //Y:coninue
//N:right way
if( !this->wasCome( tmp_elem))
{//this is a new branch
break;
}
tmp_from =(ORIEN)( tmp_from + 1); //next orientation
} elem = tmp_elem;
from = tmp_from;
return true;
} /**
* arrive the exit of maze ? */
bool BOY::isEnd(void)
{
if( (this->cur.x==END_X)
&&(this->cur.y ==END_Y))
{
return true;
} return false;
} /**
* find a visible path that is not block. It use @c_elem as the current view point,
* if success , write information into @elem and @from.
*/
bool BOY::findVisible( ELEMENT &c_elem, ELEMENT &elem, ORIEN& from)
{
ELEMENT tmp;
/*
* check valid path clockwise.
*/
switch( from)
{
case O_RIGHT:
if( (this->map.right( c_elem.x, c_elem.y, tmp))
&&( tmp.val == T_NOR))
{
elem = tmp;
from = O_RIGHT;
return true;
}
case O_DOWN:
if( (this->map.down( c_elem.x, c_elem.y, tmp))
&&( tmp.val == T_NOR))
{
elem = tmp;
from = O_DOWN;
return true;
}
case O_LEFT:
if( (this->map.left( c_elem.x, c_elem.y, tmp))
&&( tmp.val == T_NOR))
{
elem = tmp;
from = O_LEFT;
return true;
}
case O_UP:
if( (this->map.up( c_elem.x, c_elem.y, tmp))
&&( tmp.val == T_NOR))
{
elem = tmp;
from = O_UP;
return true;
}
default :;
} return false;
} /**
* Though this function is very tiny, it hold a important position
* in the totally algorithm. The upper function will call this to ensure
* whether a node is deserve to visit. By add a series of strategies
* we could improve the algorithm.
*/
bool BOY::wasCome( ELEMENT &c_elem)
{
#if 1
//label
return c_elem.hasComing;
#else
//标准1
if( c_elem.hasComing)
return true; //标准2
ELEMENT elem;
this->stack.reset_v();
while( this->stack.pop_v( elem))
{
if( (c_elem.x==elem.x)
&&(c_elem.y==elem.y))
return true;
} return false; //wasn't coming #endif
} /**
* show the status of map
*/
bool BOY::ShowMap(void)
{
printf("-----------MAP---------------------\n");
COORDINATE i,j;
for( i=0; i<MAP_WID; i++)
{
for( j=0; j<MAP_WID; j++)
{
ELEMENT tmp;
if(!this->map.cur( i, j, tmp))
{
printf("error: [ %d, %d]\n", i, j);
return false;
}
printf("%3d", tmp.val);
}
printf("\n");
} return true;
} /**
* show the status of stack, just visit it and don't pop element from it
*/
bool BOY::ShowStack(void)
{
printf("-----------STACK---------------------\n"); ELEMENT tmp_elem; this->stack.reset_v( );
while( this->stack.pop_v( tmp_elem))
{
printf("[ %d, %d]\n", tmp_elem.x, tmp_elem.y);
}
} int main()
{
BOY boy;
boy.ShowMap( );
boy.work( );
boy.ShowStack( );
return 0;
}

迷宫问题的C语言求解的更多相关文章

  1. 应用栈解决迷宫问题的C语言实现

    题目来自于严蔚敏<数据结构>,参考伪代码实现的程序: #include <stdio.h> #include <malloc.h> //记录通道块在迷宫矩阵当中的横 ...

  2. Leetcode 20题 有效的括号(Valid Parentheses) Java语言求解

    题目描述: 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空 ...

  3. s=1+2*3+4*5*6+7*8*9*10+.... C语言求解

    #include <stdio.h> /*类似斐波那契数列的计算方式 项 1 2 3 4 1 2*3 4*5*6 7*8*9*10 生成项的起始数字 1 2 4 7 和后一项的差值 1 2 ...

  4. Leetcode 239题 滑动窗口最大值(Sliding Window Maximum) Java语言求解

    题目链接 https://leetcode-cn.com/problems/sliding-window-maximum/ 题目内容 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧 ...

  5. Leetcode 703题数据流中的第K大元素(Kth Largest Element in a Stream)Java语言求解

    题目链接 https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/ 题目内容 设计一个找到数据流中第K大元素的类(class) ...

  6. LeetCode 225题用队列实现栈(Implement Stack using Queues) Java语言求解

    链接 https://leetcode-cn.com/problems/implement-stack-using-queues/ 思路 首先演示push()操作:将元素依次进入队1,进入时用top元 ...

  7. LeetCode 232题用栈实现队列(Implement Queue using Stacks) Java语言求解

    题目链接 https://leetcode-cn.com/problems/implement-queue-using-stacks/ 题目描述 使用栈实现队列的下列操作: push(x) -- 将一 ...

  8. Leetcode 206题 反转链表(Reverse Linked List)Java语言求解

    题目描述: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 迭代解 ...

  9. Leetcode 142题 环形链表 II(Linked List Cycle II) Java语言求解

    题目描述: 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 p ...

随机推荐

  1. 1 、在Linux(centos6.8)系统下的JDK安装与配置

    一.解压jdk安装包: 附上jdk1.8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21 ...

  2. **如何让CI框架支持service层

    http://www.bitscn.com/pdb/php/201411/404708.html 大家知道CodeIgniter框架式MVC分层的,通常大家把业务逻辑写到Controller中,而Mo ...

  3. Spring AOP实现原理-动态代理

    目录 代理模式 静态代理 动态代理 代理模式 我们知道,Spring AOP的主要作用就是不通过修改源代码的方式.将非核心功能代码织入来实现对方法的增强.那么Spring AOP的底层如何实现对方法的 ...

  4. Yeoman generator

    使用Yeoman generator来规范工程的初始化 前言 随着开发团队不断发展壮大,在人员增加的同时也带来了协作成本的增加:业务项目越来越多,类型也各不相同.常见的类型有基础组件.业务组件.基于R ...

  5. windows下安装mysql8.0压缩版

         下面总结下安装过程: 首先解压下载好的压缩版本. 将解压后mysql的bin文件目录配置系统环境path变量中 使用cmd打开命令窗口,输入mysqld  --initialize命令初始化 ...

  6. 2017 icpc 沈阳 G - Infinite Fraction Path

    题目大意:有n个点, 每个点有一个数字0 - 9, 第 i 个点只能到 第(i * i + 1)个点,问你在哪个点出发走n次构成的数字串最大. 思路:利用求后缀数组的倍增比较思想, 许多细节需要注意. ...

  7. 少走弯路,一个老程序猿谈PHP职业发展规划

    PHP是一个使用者非常多的开发语言,但在每个领域里的开发侧重点有所不同互联网方面,在稳定的基础上,更注重性能.高并发,高负载的处理. PHP职业发展规划一般有三条路线,一条技能专精发展路线.另两条,是 ...

  8. React Hooks新特性学习随笔

    React Hooks 是 React 16.8 的新增特性.它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性. 前言 本篇主要以讲几个常用的api为主. 1.u ...

  9. ApiPost的环境变量的定义和使用「ApiPost环境变量」

    新版的ApiPost(Chrome拓展V2.0.8+/客户端V2.2.1+)已经支持环境变量的定义和使用. 本文主要介绍ApiPost环境变量的第一课:如何定义环境变量,并如何使用它. ApiPost ...

  10. 前端网页、php与mysql数据库字符编码(解决中文等乱码问题)

    web开发中经常涉及前端网页——php——mysql之间的数据交互,当数据只有英文时通常不会有什么问题,但一旦涉及中文,三个地方的某一处字符编码不一致(如,网页使用的时gbk而mysql使用utf-8 ...