【题解】密室逃脱

题面描述

即使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
", 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
");
//			}
			if(i + x[k] < 1 || i + x[k] > n || j + y[k] < 1 || j + y[k] > n){
//				if(fl == 1)printf("died 1
");
				continue;
			}	
			if(bd[i + x[k]][j + y[k]] == '#'){
//				if(fl == 1)printf("died 2
");
				continue;
			}
			if(f[i + x[k]][j + y[k]][keynow] != -1){
//				if(fl == 1)printf("died 3
");
				continue;
			}		
			if(bd[i + x[k]][j + y[k]] == '0' + keynow + 1){
//				printf("*%d %d
", 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
", i + x[k], j + y[k], keynow, f[i + x[k]][j + y[k]][keynow]);
		}
	}
}
void dfs(int pos, int chosn){
//	printf("%d %d
", 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
", 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 << "
";
//	}
//	printf("%d %d %d %d
", tx, ty, ex, ey);
	dfs(1, 0);
	if(ans < 1000000000)
		printf("%lld
", ans);
	else printf("impossible
");
	return 0;
}

原文地址:https://www.cnblogs.com/ZhengkunJia/p/14417246.html