NOIp模拟题 T3 密室逃脱
题面
即使 czhou 没有派出最强篮球阵容,机房篮球队还是暴虐了校篮球队。为了不打击校篮球队信心,czhou 决定改变训练后的活动。近来,江大掌门的徒弟徒孙们纷纷事业有成,回到母校为机房捐钱捐物。财大气粗的机房组收回了五层六层的所有教室。Czhou 决定将六层的教室改造为智能密室逃脱活动室。每天傍晚,神牛们可以依次逐个进入游玩。我们简单的将教室分割为 n*n 个房间,K 是你初始所在房间,T 是你最终逃脱的房间。如果你想要逃脱房间,你必须依次找到 m 把钥匙。我们假定你从一个房间进入另一个房间需要花费 1 的时间。当然某些房间有些特殊的问题(地图上 S 表示)需要回答才能通过,对于机智的众牛们来说,这些问题根本不是问题。我们假定众牛们花费 1 的时间解决问题。(主要是出题的人表述不清,导致众牛理解困难;当然
问题只需要回答一次,下次再次进入房间不需要回答了)
Input:maze.in
第一行两个数字 n,m
接下来 n*n 描述地图
Output: maze.out
需要最少时间逃脱密室。若无解输出 impossible
Sample1.in:
3 1
K.S
##1
1#T
Sample1.out
5
Sample2.in
3 1
K#T
.S#
1#.
Sample2.out
impossible
Sample3.in
3 2
K#T
.S.
21.
Sample3.out
8
样例 3 说明:
要先取钥匙 1,再取钥匙 2。地图上可能有多个同一种钥匙,#为墙壁即不可走.
数据范围:\(0 < N \leq 100\), \(0 \leq M \leq 9\) , \(S\)的个数不超过\(5\)。
思路
看到迷宫加上最少步数果断bfs,但是难点在于走的时候难以记录某一个S是否走过。但是我们注意到S的个数很少,所以直接暴力枚举\(2^5\)看看每一个S有没有走过。如果走过那么就将这个S变成.,答案++;如果没走那么就把它变成#。这样对每一个选取S的方案进行bfs,得出最终的答案即可。总时间复杂度\(O(n^2*m*2^5)\)。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int ans=2147483647;
int n,m,tot,sx,lx,sy,ly;
char a[110][110];
int f[110][110][20];
int qx[100010],qy[100010],qm[100010];
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
int x[20],y[20];
void bfs(){
memset(f,-1,sizeof(f));
qx[0]=sx;qy[0]=sy;
int head=0,tail=1;
f[sx][sy][0]=0;
while(head!=tail){
int x=qx[head],y=qy[head],t=qm[head];
head++;
for(int i=0;i<4;i++){
int nowx=x+xx[i],nowy=y+yy[i],nowm=t;
if(nowx<1||nowy<1||nowx>n||nowy>n) continue;
if(nowm+1==a[nowx][nowy]-'0') nowm++;
if(a[nowx][nowy]=='#'||f[nowx][nowy][nowm]!=-1) continue;
f[nowx][nowy][nowm]=f[x][y][t]+1;
qx[tail]=nowx;
qy[tail]=nowy;
qm[tail]=nowm;
tail++;
}
}
}
void dfs(int now,int k){
if(now==tot+1){
bfs();
if(f[lx][ly][m]!=-1){
ans=min(ans,k+f[lx][ly][m]);
}
return;
}
a[x[now]][y[now]]='.';
dfs(now+1,k+1);
a[x[now]][y[now]]='#';
dfs(now+1,k);
}
int main()
{
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
if(a[i][j]=='K'){
sx=i;sy=j;
}
else if(a[i][j]=='T'){
lx=i;ly=j;
}
else if(a[i][j]=='S'){
tot++;
x[tot]=i;y[tot]=j;
}
}
}
dfs(1,0);
if(ans==2147483647){
printf("impossible\n");
}
else{
printf("%d\n",ans);
}
return 0;
}