百炼 4130: Saving Tang Monk

博客提到同一个S可能需多次经过,但只需杀一次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

同一个S可能需要多次经过,只需杀一次。

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 100 + 5;

char s[N][N];
int si, sj, n, m, ei, ej, p[N][N];

struct Node {
	int x, y, key, dis, snack;
	Node(int x = 0, int y = 0, int key = 0, int dis = 0, int snack = 0) :x(x), y(y), key(key), dis(dis), snack(snack) {}
	bool operator<(const Node& n)const {
		return dis > n.dis;
	}
};

int dir[][4] = { {-1,1,0,0},{0,0,-1,1} };
int d[N][N][10];

int bfs() {
	priority_queue<Node> q;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			for (int k = 0; k <= m; k++)
				d[i][j][k] = 0x3f3f3f3f;
	q.push(Node(si, sj, 0, 0, 0));
	d[si][sj][0] = 0;
	while (!q.empty()) {
		Node tp = q.top();
		q.pop();
		for (int i = 0; i < 4; i++) {
			int ii = tp.x + dir[0][i];
			int jj = tp.y + dir[1][i];
			if (0 <= ii && ii < n && 0 <= jj && jj < n && s[ii][jj] != '#') {
				if (s[ii][jj] == 'S') {
					if ((tp.snack >> p[ii][jj]) & 1)
					{
						if (tp.dis + 1 < d[ii][jj][tp.key])
							d[ii][jj][tp.key] = tp.dis + 1, q.push(Node(ii, jj, tp.key, tp.dis + 1, tp.snack));
					}
					else {
						if (tp.dis + 2 < d[ii][jj][tp.key])
							d[ii][jj][tp.key] = tp.dis + 2, q.push(Node(ii, jj, tp.key, tp.dis + 2, tp.snack | (1 << p[ii][jj])));
					}
				}
				else if ('1' <= s[ii][jj] && s[ii][jj] <= '9') {
					if (s[ii][jj] - '0' == tp.key + 1) {
						if (tp.dis + 1 < d[ii][jj][tp.key + 1]) {
							d[ii][jj][tp.key + 1] = tp.dis + 1, q.push(Node(ii, jj, tp.key + 1, tp.dis + 1, tp.snack));
						}
							
					}
					else {
						if (tp.dis + 1 < d[ii][jj][tp.key])
							d[ii][jj][tp.key] = tp.dis + 1, q.push(Node(ii, jj, tp.key, tp.dis + 1, tp.snack));
					}
				}
				else if (s[ii][jj] == 'T') {
					if (tp.key == m)
						return tp.dis + 1;
					else{
						if (tp.dis + 1 < d[ii][jj][tp.key])
							d[ii][jj][tp.key] = tp.dis + 1, q.push(Node(ii, jj, tp.key, tp.dis + 1, tp.snack));
					}
				}
				else {
					if (tp.dis + 1 < d[ii][jj][tp.key])
						d[ii][jj][tp.key] = tp.dis + 1, q.push(Node(ii, jj, tp.key, tp.dis + 1, tp.snack));
				}
			}
		}
	}
	return -1;
}

int main(){
	for (; scanf("%d%d", &n, &m) == 2 && n + m;) {
		si = -1, sj = -1, ei = -1, ej = -1;
		for (int i = 0; i < n; i++)
			scanf("%s", s[i]);
		int cnt = 0;
		for(int i=0;i<n;i++)
			for (int j = 0; j < n; j++)
			{
				if (s[i][j] == 'K')
					si = i, sj = j;
				else if (s[i][j] == 'T')
					ei = i, ej = j;
				else if (s[i][j] == 'S') 
					p[i][j] = cnt++;
			}
		if (ei == -1 || si == -1) {
			printf("impossible\n");
		}
		else {
			int ans = bfs();
			if (ans != -1) printf("%d\n", ans);
			else printf("impossible\n");
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值