ZOJ中一些BFS题目的练习

本文详细介绍了在ZOJ(浙江大学在线评测系统)中的一些使用BFS(宽度优先搜索)解决的题目,包括三维迷宫最短路径、矩阵状态转换最小步数和二维迷宫中避开炸弹的最短路径等。通过这些实例展示了BFS在不同问题中的应用策略和实现方法。
摘要由CSDN通过智能技术生成

关于一些BFS的题目:

ZOJ1438 :  http://acm.zju.edu.cn/show_problem.php?pid=1438

一道最基础的BFS,就是求在三维迷宫中从一个点到另外一个点的最短距离.

就是在输入的时候它不像以前那样先行再列最后层数,要小心

/*

*  简单的BFS

*  由于输入问题一开始WAn

*/

#include <iostream>

#include <deque>

#include <string>

 

using namespace std ;

 

struct Node

{

         int x, y, z ;

}temp, t, aim ;

 

deque<Node> de[2] ;

 

bool mark[12][12][12] ;

char maze[12][12][12] ;

int Size, step ;

int walk[6][3] ;

 

bool operator ==(Node &a, Node &b)

{

         if ( a.x == b.x && a.y == b.y && a.z == b.z ) return true ;

         return false ;

}

void initi()

{

         int i, j, k ;

         for ( k = 0 ; k < Size ; k++ ) {

                   for ( j = 0 ; j < Size ; j++ ) {

                            getchar() ;

                            for ( i = 0 ; i < Size ; i++ ) {

                                     scanf ( "%c", &maze[i][j][k] ) ;

                                     mark[i][j][k] = false ;

                            }

                   }

         }

         scanf ( "%d%d%d", &temp.x, &temp.y, &temp.z ) ;

         scanf ( "%d%d%d", &aim.x, &aim.y, &aim.z ) ;

         mark[temp.x][temp.y][temp.z] = true ;

         de[0].clear() ; de[1].clear() ;

         de[0].push_back(temp) ;

         step = 0 ;

}

 

void work()

{

         int now = 0, n, i ;

         while ( !de[0].empty() || !de[1].empty() ) {

                   n = now^1 ;

                   while ( !de[now].empty() ) {

                            temp = de[now].front() ;

                            de[now].pop_front() ;

                            if ( temp == aim ) {

                                     printf ( "%d %d/n", Size, step ) ;

                                     return ;

                            }

                            for ( i = 0 ; i < 6 ; i++ ) {

                                     t.x = temp.x+walk[i][0] ;

                                     t.y = temp.y+walk[i][1] ;

                                     t.z = temp.z+walk[i][2] ;

                                     if ( t.x < 0 || t.y < 0 || t.z < 0

                                               || t.x >= Size || t.y >= Size || t.z >= Size ) continue ;

                                     if ( maze[t.x][t.y][t.z] == 'O' && !mark[t.x][t.y][t.z] ) {

                                               mark[t.x][t.y][t.z] = true ;

                                               de[n].push_back(t) ;

                                     }

                            }

                   }

                   now = n ;

                   step ++ ;

         }

         printf ( "NO ROUTE/n" ) ;

}

void init()

{

         walk[0][0] = 1 ; walk[0][1] = 0 ; walk[0][2] = 0 ;

         walk[1][0] = 0 ; walk[1][1] = 1 ; walk[1][2] = 0 ;

         walk[2][0] = 0 ; walk[2][1] = 0 ; walk[2][2] = 1 ;

         walk[3][0] = -1 ; walk[3][1] = 0 ; walk[3][2] = 0 ;

         walk[4][0] = 0 ; walk[4][1] = -1 ; walk[4][2] = 0 ;

         walk[5][0] = 0 ; walk[5][1] = 0 ; walk[5][2] = -1 ;

}

 

int main ( void )

{

         string str ;

         init() ;

         while ( cin >> str >> Size ) {

                   initi() ;

                   cin >> str ;

                   work() ;

         }

         return 0 ;

}

 

ZOJ2050 : http://acm.zju.edu.cn/show_problem.php?pid=2050

题目意思就是从输入状态一直换,知道矩阵中全是b状态或者全是w状态,换的方法是随便从矩阵中选一个值出来,和它相临的全部取反(包括它自己这个点也取反).

就是BFS从一个状态换到另外一个状态的最少步数,关键在于如何存状态,由于位数是确定的,所以想到用16位的位运算.

/*

*  0.07s  BFS

*/

#include <iostream>

#include <deque>

 

using namespace std ;

 

deque<int> de[2] ;

int value[18], walk[5][2] ;

bool mark[65536] ;

int step ;

 

void initi()

{

         int i, j ;

         int num = 0 ;

         char ch ;

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

                   while ( ch = getchar() ) {

                            if ( ch == 'b' || ch =='w' ) break ;

                   }

                   num = num << 1 ;

                   if ( ch == 'b' ) num ++ ;

                   for ( j = 0 ; j < 3 ; j++ ) {

                            ch = getchar() ;

                            num = num << 1 ;

                            if ( ch == 'b' ) num ++ ;

                   }

         }

         de[0].clear() ; de[1].clear() ;

         de[0].push_back(num) ;

         step = 0 ;

         memset(mark,false,sizeof(mark)) ;

         mark[num] = true ;

}

 

void work()

{

         int now = 0, n, i, j, k ;

         int temp ;

         while ( !de[0].empty() || !de[1].empty() ) {

                   n = now^1 ;

                   while ( !de[now].empty() ) {

                            temp = de[now].front() ;

                            de[now].pop_front() ;

                            if ( temp == 0 || temp == 65535 ) { cout << step << endl ; return ; }

                            int x, y ;

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

                                     for ( j = 0 ; j < 4 ; j++ ) {

                                               x = temp ;

                                               for( k = 0 ; k < 5 ; k++ ) {

                                                        int a = i+walk[k][0] ;

                                                        int b = j+walk[k][1] ;

                                                        if ( a < 0 || b < 0 || a >= 4 || b >= 4 ) continue ;

                                                        y = 16-(a*4+b) ;

                                                        if ( 1&(x>>y-1) ) {

                                                                 x = ~x ;

                                                                 x = x|value[y] ;

                                                                 x = ~x ;

                                                        }

                                                        else x = x|value[y] ;

                                               }

                                               if ( !mark[x] ) { de[n].push_back(x) ; mark[x] = true ; }

                                     }

                            }

                   }

                   now = n ;

                   step ++ ;

         }

         cout << "Impossible" << endl ;

}

 

void init()

{

         walk[4][0] = 0 ; walk[4][1] = 0 ;

         walk[0][0] = 1 ; walk[0][1] = 0 ;

         walk[1][0] = 0 ; walk[1][1] = 1 ;

         walk[2][0] = -1 ; walk[2][1] = 0 ;

         walk[3][0] = 0 ; walk[3][1] = -1 ;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值