广搜,值得学习的地方时是用二进制数来存储已获得的钻石种类。
#include <iostream>
#include <memory.h>
#include <vector>
#include <queue>
#include <stdio.h>
#include <algorithm>
#include <unordered_set>
#include <set>
#define IN (1<<28)
using namespace std;
struct node
{
int x,y,step, dia;
node( int xx = 0, int yy = 0, int ss = 0, int dd = 0 ):x(xx), y(yy), step(ss), dia(dd) {}
friend bool operator <(const node &a, const node &b )
{
return a.step > b.step;
}
};
struct door
{
int x,y;
door( int xx = 0, int yy = 0):x(xx), y(yy) {}
};
door doors[15];
queue<node> q;
int visited[205][205][1<<5], R, C, K, T, BeginX, BeginY, EndX, EndY, cnt;
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
char Map[205][205];
void bfs()
{
if( K > 5 )
{
printf("oop!\n");
return;
}
q.push( node( BeginX, BeginY, 0, 0 ) );
visited[BeginX][BeginY][0] = 1;
while( !q.empty() )
{
node now = q.front();
q.pop();
if( now.x == EndX && now.y == EndY && now.dia >= (1<<K) - 1 )
{
printf("%d\n", now.step );
return;
}
if( Map[now.x][now.y] == '$' )
{
for( int i = 0; i < cnt; i++ )
{
if( !visited[ doors[i].x ][ doors[i].y ][ now.dia ] )
{
q.push( node( doors[i].x, doors[i].y, now.step, now.dia ) );
visited[ doors[i].x ][ doors[i].y ][ now.dia ] = 1;
}
}
}
for( int i = 0; i < 4; i++ )
{
int nowx = now.x + dx[i];
int nowy = now.y + dy[i];
if( Map[nowx][nowy] != '#' )
{
if( Map[nowx][nowy] >= '0' && Map[nowx][nowy] <= '4' )
{
int s;
s = now.dia | (1<<Map[nowx][nowy]-'0');
if( !visited[nowx][nowy][s] )
{
q.push( node( nowx, nowy, now.step + 1, s ) );
visited[nowx][nowy][s] = 1;
}
}
else
{
if( !visited[nowx][nowy][now.dia] )
{
q.push( node( nowx, nowy, now.step + 1, now.dia ) );
visited[nowx][nowy][now.dia] = 1;
}
}
}
}
}
printf("oop!\n");
return;
}
int main()
{
scanf("%d", &T);
while( T-- )
{
scanf("%d %d %d", &R, &C, &K);
memset(visited, 0, sizeof(visited));
for( int i = 0; i < 205; i++ )
for( int j = 0; j < 205; j++ )
Map[i][j] = '0';
cnt = 0;//传送门数量
while( !q.empty() )
{
q.pop();
}
for( int i = 1; i <= R; i++ )
for( int j = 1; j <= C; j++ )
{
cin >> Map[i][j];
if( Map[i][j] == 'S' )
{
BeginX = i;
BeginY = j;
}
else if( Map[i][j] == 'E' )
{
EndX = i;
EndY = j;
}
else if( Map[i][j] == '$' )
{
doors[cnt].x = i;
doors[cnt].y = j;
cnt++;
}
}
for( int i = 0; i <= R+1; i++ )
for( int j = 0; j <= C+1; j++ )
{
if( i==0 || j==0 || i==R+1 || j==C+1 )
Map[i][j] = '#';
}
bfs();
}
return 0;
}