您的位置:首页 > 其它

uva 10047

2013-12-14 20:02 288 查看
这是一道复合状态的迷宫搜索题 。

对vis数组的理解: 以前一直以为这只是一个标记每个点事否走过的数组 , 其实这只是片面的认识 , 它标记的不是一个点 ,
而是一个“状态” , 状态和点是不一样的 , 点是单一的 , 而状态不只是表示一个点 , 更是表示这个点所处在的状态 。

这个题要把方向 , 颜色 , 点 ,一起看成一个综合的状态 , 那就意味着要定义一个四维数组 。

用bfs有两种方法 :

1、用优先队列 , 那么就可以减小很多内存的消耗 , 且速度也更快 。

用优先队列 , 可以不记录只改变方向点不变的状态 , 就是让这个点“改变方向+按这个方向走向下一个点”,一步完成 。如果这样的话 ,
会产生一种情况 , 就是同一次bfs遍历到的点 , 所花的时间是不一样的。所以 , 如果按照这个情况bfs下去 ,
并且取第一次到时间为最优时间,这样是有漏洞的 。

2、不用优先队列 , 但是只改变方向的状态也必须要记录 , 这样同时遍历到的点所花的时间就是一样的了 ,bfs最先找到的也就是最优的解


第一种情况的代码:

#include

#include

#include

#include

using namespace std ;

const int maxn = 25 + 10 ;

//一个状态的五个属性,坐标,方向,步数

struct Node { int x ; int y ; int d ; int s ; int c ; } node1 ,
node2 ;

//优先队列

struct cmp

{

    bool
operator () (const Node a, const Node b)

    {

       
return a.s > b.s;

    }

};

priority_queue ,cmp > q ;

//queue < Node > q ;

//一般队列不能用,因为队首可能不是最优的,因为当你得到一个状态扩展出来的所有状态时,

//你需要且只需要最优的那一个,所以优先队列成为必然的选择(当然你也可以在所有状态中找到当前最优的一个状态,嘿嘿)

char map[maxn][maxn] ;

bool visit[maxn][maxn][5][4] ;//标记状态数组

int r , c ;//行列

int bx , by , ex , ey ;//开始位置与终点位置

int ans ;//最小步数

int flag ;//标记是否有解

int dx[] = { -1 , 1 , 0 , 0 } ;//控制x方向

int dy[] = { 0 , 0 , -1 , 1 } ;//控制y方向

int dd[] = { 0 , 1 , 2 , 3 } ;//北,南,西,东(上,下,左,右)

//初始化

void init()

{

    bx = by = ex
= ey = 0 ;

    ans = 0 ;
flag = 0 ;

    while( !
q.empty() ) q.pop() ;

    memset( map
, 0 , sizeof( map ) ) ;

    memset(
visit , 0 , sizeof( visit ) ) ;

    for( int i =
0 ; i < r ; ++i )

    {

       
for( int j = 0 ; j < c ; ++j )

       
{

           
cin >> map[i][j] ;

           
if( map[i][j] == 'S' )

           
{ bx = i ; by = j ; }

           
if( map[i][j] == 'T' )

           
{ ex = i ; ey = j ; }

       
}

    }

    return
;

}

//判断状态是否出现过

bool is_ok( int x , int y , int cc , int d )

{

    if( x < 0
|| y < 0 || x >= r || y >= c || map[x][y] == '#' ||
visit[x][y][cc][d] )

    return false
;

    return true
;

}

//得到步数

int get_step( int nd , int d , int s )

{

    if( d == 0
&& nd == 1 ) return s + 2 ;

    else if( d
== 1 && nd == 0 ) return s + 2 ;

    else if( d
== 2 && nd == 3 ) return s + 2 ;

    else if( d
== 3 && nd == 2 ) return s + 2 ;

    else return
s + 1 ;

}

//判断是否为解

bool is_ans( int x , int y , int cc )

{

    if( x != ex
|| y != ey || cc )

    return false
;

    return true
;

}

//广度优先搜索

void bfs()

{

   
//初始化队首

    node1.x = bx
, node1.y = by , node1.c = 0 , node1.s = 0 , node1.d = 0 ;

    q.push(
node1 ) ;

   
visit[bx][by][node1.c][node1.d] = true ;

    while( !
q.empty() )

    {

       
node1 = q.top() ;

       
q.pop() ;

       
int x = node1.x ;

       
int y = node1.y ;

       
int c = node1.c ;

       
int s = node1.s ;

       
int d = node1.d ;

       
for( int i = 0 ; i < 4 ; ++i )

       
{

           
int nd = dd[i] ;

          
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: