hdu 5025 bfs+状态压缩

首先因为钥匙是顺序拿取的,所以记录当前取到第几把就可以

因为杀蛇是无序的,所以要用0/1二进制数表示

然后宽搜就好了.......wrong了一天就是读入问题,默默反省

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <queue>
#define MAX 107

using namespace std;

int n,m,ans;
char ch;
int mp[MAX][MAX];
int mark[MAX][MAX][11][68];

struct Point
{
    int x,y,k,s,t;
}st,tmp;

int dx[] = { 0 , 0 , 1 , 0 , -1 };
int dy[] = { 0 , 1 , 0 , -1,  0 };

void bfs ( )
{
    queue<Point> q;
    mark[st.x][st.y][st.k][st.s] = 1;
    q.push ( st );
    while ( !q.empty() )
    {
        st = q.front( );
        q.pop();
        if ( st.k == m+1 )
        {
            if ( ans == -1 ) ans = st.t;
            else ans = min ( ans , st.t );
        }
        for ( int i = 1 ; i <= 4 ; i++ )
        {
            tmp.x = st.x + dx[i] , tmp.y = st.y + dy[i],
            tmp.s = st.s , tmp.k = st.k , tmp.t = st.t+1;
            int value = mp[tmp.x][tmp.y];
            if ( value  < 0 ) continue;
            if ( value > m+2 )
            {
                int j = value-m-3;
                if ( !(tmp.s&(1<<j)) ) tmp.s|=(1<<j) , tmp.t++;
            }
            if ( 1 <= value <= m+1  )
                if ( tmp.k == value - 1 ) tmp.k++;
            if ( mark[tmp.x][tmp.y][tmp.k][tmp.s] <= tmp.t ) continue;
            mark[tmp.x][tmp.y][tmp.k][tmp.s] = tmp.t;
            q.push ( tmp );
        }   
    }
}


void out ( )
{
    for ( int i = 1 ; i <= n ; i++  )
    {
       for ( int j = 1 ; j <= n ; j++ )
          cout << mp[i][j] << " ";
       cout << endl;
    }
}


int main ( )
{
    while ( ~scanf ( "%d%d" , &n , &m ) )
    {
        if ( !n && !m ) break;
        ans = -1;
        char s[500];
        memset ( mark , 0x3f , sizeof ( mark ) );
        memset ( mp , -1 , sizeof ( mp ) );
        int cnt = 0;
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%s" , s+1 );
            for ( int j = 1 ; j <= n ; j++ )
            {
               ch = s[j];
               if ( ch == '.' ) mp[i][j] = m+2;
               if ( ch == 'K' ) mp[i][j] = 0 , st.x = i , st.y = j;
               if ( ch == 'T' ) mp[i][j] = m+1;
               if ( ch == 'S' ) mp[i][j] = m+3+(cnt++);
               if ( isdigit(ch)) mp[i][j] = ch - 48;
            }
        }
        st.k = st.s = st.t = 0;
        //cout << sx << " " << sy << endl;
        //out ( );
        bfs ( );
        if ( ans == -1 )
            puts ( "impossible" );
        else printf ( "%d\n" , ans );
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值