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;
}
posted @ 2021-02-19 16:18  徐明拯  阅读(123)  评论(0编辑  收藏  举报