杭电1429--胜利大逃亡(续)(Bfs+状态压缩)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1429

题意:迷宫问题, 多了门和钥匙。 

第一道状态压缩, 利用二进制来保存是否得到钥匙, 三维数组Judge[][][], 记录状态, 为什么会走“回头路”, 因为在所走步数最少的情况下, 走回头路的情况只能是取钥匙再回来的时候才有, 但是取完钥匙后,虽在同一点但其状态已将变化(钥匙 有-->无)。 可以看作把钥匙加入钥匙串。

利用二进制判断钥匙是否在串中 或加入钥匙串:

判断门是否会打开时用 钥匙与门编号进行'&'----> 例如: 1000100010 & 0000100000 != 0 说明可以打开‘A’ + 6这道门。

如果碰到钥匙要加入该钥匙。将钥匙加入钥匙串要进行'|' ---->例如:1000100010 |  0000010000 = 1000110010;’e'入串。 

知道了这些, 就直接可以跑Bfs了 ^~^!

 

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using  namespace std; 
char map[ 21][ 21];  int ac[ 4][ 2] = { 010, - 1, - 1010};
bool Judge[ 21][ 21][ 1025]; 
int n, m, T; 
struct Maze
{
     int x, y, step, Key;
} r, s, t;
int Bfs( int a,  int b)
{
    r.x = a; r.y = b; r.step =  0; r.Key =  0;
    Judge[a][b][ 0] =  true;
    queue<Maze> Q;
    Q.push(r);
     while(!Q.empty())
    {
        s = Q.front(); Q.pop();
     //     printf("%d %d\n", s.x, s.y);
         for( int i =  0; i <  4; i++)
        {
            t.x = s.x + ac[i][ 0]; 
            t.y = s.y + ac[i][ 1];
            t.step = s.step +  1;
            t.Key = s.Key;
             if(t.x >=  0 && t.x < n && t.y >=  0 && t.y < m && map[t.x][t.y] !=  ' * ' && t.step < T && !Judge[t.x][t.y][t.Key])
            { 
                 if(map[t.x][t.y] ==  ' ^ ')
                     return t.step;
                 if(map[t.x][t.y] >=  ' a ' && map[t.x][t.y] <=  ' j ')
                {
                     int temp = map[t.x][t.y] -  ' a ';
                     if((t.Key & ( 1 << temp)) ==  0)       // 小细节, 位运算作比较用时要加括号!!!!!! 
                        t.Key += ( 1 << temp);    
                }    
                 if(map[t.x][t.y] >=  ' A ' && map[t.x][t.y] <=  ' J ')
                {
                     int temp = map[t.x][t.y] -  ' A '
                     if((t.Key & ( 1 << temp)) ==  0)
                         continue;
                }
                Judge[t.x][t.y][t.Key] =  true;
                Q.push(t); 
            } 
        }
    } 
     return - 1;
}
int main()
{
     while(~scanf( " %d %d %d ", &n, &m, &T))
    {
         int x, y;
         for( int i =  0; i < n; i++)
        {
            scanf( " %s ", map[i]);
             for( int j =  0; j < m; j++)
            {
                 if(map[i][j] ==  ' @ ')
                    x= i, y = j, map[i][j] =  ' . '
            }
        }
        memset(Judge,  falsesizeof(Judge));
        printf( " %d\n ", Bfs(x, y));
    }
     return  0; }   


 

转载于:https://www.cnblogs.com/soTired/p/4780595.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值