首先因为钥匙是顺序拿取的,所以记录当前取到第几把就可以
因为杀蛇是无序的,所以要用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 );
}
}