【题解】密室逃脱
题面描述
即使czhou没有派出最强篮球阵容,机房篮球队还是暴虐了校篮球队。为了不打击校篮球队信心,czhou决定改变训练后的活动。近来,江大掌门的徒弟徒孙们纷纷事业有成,回到母校为机房捐钱捐物。财大气粗的机房组收回了五层六层的所有教室。Czhou决定将六层的教室改造为智能密室逃脱活动室。
每天傍晚,神牛们可以依次逐个进入游玩。我们简单的将教室分割为n*n个房间,K是你初始所在房间,T是你最终逃脱的房间。如果你想要逃脱房间,你必须依次找到m把钥匙。我们假定你从一个房间进入另一个房间需要花费1的时间。当然某些房间有些特殊的问题(地图上S表示)需要回答才能通过,对于机智的众牛们来说,这些问题根本不是问题。我们假定众牛们花费1的时间解决问题。(主要是出题的人表述不清,导致众牛理解困难;当然问题只需要回答一次,下次再次进入房间不需要y回答了)
Input:maze.in
第一行两个数字n,m
接下来n*n描述地图
Output: maze.out
需要最少步数逃脱密室。若无解输出impossible
Sample1.in:
3 1
K.S
1
1#T
Sample1.outvb
5
Sample2.in
3 1
K#T
.S#
1#.
Sample2.out
Impossible
Sample3.in
3 2
K#T
.S.
Sample3.out
8
样例3说明:
要先取钥匙1,再取钥匙2。地图上可能有多个同一种钥匙,#为墙壁即不可走.
数据范围:
0 < N <= 100, 0<=M<=9,S的个数<=5
题解
因为s走过一次就消失,并且s很小,所以特殊处理,dfs搜索选哪些S,在最后的答案中加上s的额外支出
选这个s就将原地图中的相应位置设为'.',不选就设为'#'
f[i][j][k]表示走到bd[i][j]这个位置,并且当前拿到了第k种钥匙时的最短路
bfs求最短路
代码调不出来
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#include<set>
#include<map>
#define LL long long
using namespace std;
inline void Read(int &x){
int f=1;
char c=getchar();
x=0;
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
int n, m, tx, ty, ex, ey, sx[6], sy[6], cnt;
int f[105][105][11], q[10010][4], head, tail;
int x[5] = {0, 0, 0, 1, -1}, y[5] = {0, 1, -1, 0, 0};
LL ans;
int fl;
char bd[105][105];
void bfs(){
memset(f, -1, sizeof(f));
f[tx][ty][0] = 0;
q[1][1] = tx; q[1][2] = ty; q[1][3] = 0;
head = 1; tail = 1;
while(head <= tail){
int i = q[head][1], j = q[head][2], key = q[head][3]; head++;
// printf(" %d %d %d %d\n", i, j, key, f[i][j][key]);
for(int k = 1; k <= 4; ++k){
fl = 0;
int keynow = key;
// if(i + x[k] == 2 && j + y[k] == 3 && keynow == 2){
// fl = 1; printf("yep\n");
// }
if(i + x[k] < 1 || i + x[k] > n || j + y[k] < 1 || j + y[k] > n){
// if(fl == 1)printf("died 1\n");
continue;
}
if(bd[i + x[k]][j + y[k]] == '#'){
// if(fl == 1)printf("died 2\n");
continue;
}
if(f[i + x[k]][j + y[k]][keynow] != -1){
// if(fl == 1)printf("died 3\n");
continue;
}
if(bd[i + x[k]][j + y[k]] == '0' + keynow + 1){
// printf("*%d %d\n", bd[i + x[k]][j +y[k]] - '0', keynow + 1);
keynow++;
}
f[i + x[k]][j + y[k]][keynow] = f[i][j][key] + 1;
q[++tail][1] = i + x[k]; q[tail][2] = j + y[k]; q[tail][3] = keynow;
// printf("-> %d %d %d %d\n", i + x[k], j + y[k], keynow, f[i + x[k]][j + y[k]][keynow]);
}
}
}
void dfs(int pos, int chosn){
// printf("%d %d\n", pos, chosn);
if(pos == cnt + 1){
bfs();
if(f[ex][ey][m] != -1){
ans = min(ans, 0ll + f[ex][ey][m] + chosn);
printf("ans = %lld\n", ans);
}
return ;
}
bd[sx[pos]][sy[pos]] = '.';
dfs(pos + 1, chosn + 1);
bd[sx[pos]][sy[pos]] = '#';
dfs(pos + 1, chosn);
}
int main()
{
freopen("maze2.in","r",stdin);
// freopen("maze.out","w",stdout);
ans = 1000000000;
Read(n); Read(m);
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
cin >> bd[i][j];
if(bd[i][j] == 'K'){tx = i; ty = j;}
if(bd[i][j] == 'T'){ex = i; ey = j;}
if(bd[i][j] == 'S'){sx[++cnt] = i; sy[cnt] = j;}
}
}
// for(int i = 1; i <= n; ++i){
// for(int j = 1; j <= n; ++j) cout << bd[i][j] << " ";
// cout << "\n";
// }
// printf("%d %d %d %d\n", tx, ty, ex, ey);
dfs(1, 0);
if(ans < 1000000000)
printf("%lld\n", ans);
else printf("impossible\n");
return 0;
}