[状态压缩 广搜BFS]Saving Tang Monk

2024-06-21 12:04
文章标签 bfs 压缩 状态 saving tang monk

本文主要是介绍[状态压缩 广搜BFS]Saving Tang Monk,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

描述

《Journey to the West》(also 《Monkey》) is one of the Four Great Classical Novels of Chinese literature. It was written by Wu Cheng'en during the Ming Dynasty. In this novel, Monkey King Sun Wukong, pig Zhu Bajie and Sha Wujing, escorted Tang Monk to India to get sacred Buddhism texts.

During the journey, Tang Monk was often captured by demons. Most of demons wanted to eat Tang Monk to achieve immortality, but some female demons just wanted to marry him because he was handsome. So, fighting demons and saving Monk Tang is the major job for Sun Wukong to do.

Once, Tang Monk was captured by the demon White Bones. White Bones lived in a palace and she cuffed Tang Monk in a room. Sun Wukong managed to get into the palace. But to rescue Tang Monk, Sun Wukong might need to get some keys and kill some snakes in his way.

The palace can be described as a matrix of characters. Each character stands for a room. In the matrix, 'K' represents the original position of Sun Wukong, 'T' represents the location of Tang Monk and 'S' stands for a room with a snake in it. Please note that there are only one 'K' and one 'T', and at most five snakes in the palace. And, '.' means a clear room as well '#' means a deadly room which Sun Wukong couldn't get in.

There may be some keys of different kinds scattered in the rooms, but there is at most one key in one room. There are at most 9 kinds of keys. A room with a key in it is represented by a digit(from '1' to '9'). For example, '1' means a room with a first kind key, '2' means a room with a second kind key, '3' means a room with a third kind key... etc. To save Tang Monk, Sun Wukong must get ALL kinds of keys(in other words, at least one key for each kind).

For each step, Sun Wukong could move to the adjacent rooms(except deadly rooms) in 4 directions(north,west,south and east), and each step took him one minute. If he entered a room in which a living snake stayed, he must kill the snake. Killing a snake also took one minute. If Sun Wukong entered a room where there is a key of kind N, Sun would get that key if and only if he had already got keys of kind 1,kind 2 ... and kind N-1. In other words, Sun Wukong must get a key of kind N before he could get a key of kind N+1 (N>=1). If Sun Wukong got all keys he needed and entered the room in which Tang Monk was cuffed, the rescue mission is completed. If Sun Wukong didn't get enough keys, he still could pass through Tang Monk's room. Since Sun Wukong was a impatient monkey, he wanted to save Tang Monk as quickly as possible. Please figure out the minimum time Sun Wukong needed to rescue Tang Monk.

输入

There are several test cases.

For each case, the first line includes two integers N and M(0 < N <= 100, 0 <= M <= 9), meaning that the palace is a N * N matrix and Sun Wukong needed M kinds of keys(kind 1, kind 2, ... kind M).

Then the N*N matrix follows.

The input ends with N = 0 and M = 0.

输出

For each test case, print the minimum time (in minute) Sun Wokong needed to save Tang Monk. If it's impossible for Sun Wokong to complete the mission, print "impossible".

样例输入

3 1
K.S
##1
1#T
3 1
K#T
.S#
1#.
3 2
K#T
.S.
21.
0 0

样例输出

5
impossible
8
解题分析

这道题可以算是广搜的天花板之一了,不仅需要状态压缩的策略,还需要使用一些形如priority_queue的数据结构来辅助,而且关于已访问过的标记,包括拿到的钥匙,杀死的蛇等等细节都很值得推敲。以及说,我们可以用一个数组来存储我们钥匙的状态,并且我们考虑的是其二进制的表达式。首先,正常地读入数据,注意,由于我们可能有很多组数组,所以每次的while循环的开始,我们应该重置我们需要重置的一些变量,比如说访问数组归0,蛇计数数组归0,答案ans的重置。接着读入整个迷宫,需要注意的是,我们需要孙悟空的初始位置,以及我们读入蛇的时候,把这条蛇的信息放入一个数组里面,并且标记它的位置。对于我们广搜时放入priority_queue的节点的话,我们希望它有我们的位置,杀死蛇的情况,钥匙情况以及我们的步数,位置坐标和步数是很基本的。注意,我们每次的广搜,只走一步!所以我们在一次的循环里不能直接更改我们当前读取的队列开头的元素的信息,所以另设变量去处理是一个很好的选择。一共三种情况,要么是钥匙,要么是蛇,要么就是唐僧,分情况,利用位操作去判断,去处理,用&运算取出某一位,用|运算去把某一位设置为1,诸如此类,这般这般。最后输出答案即可。

代码演示
#include <iostream>
#include <cmath>
//#include <iomanip>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <bitset>
#include <queue>
#include <stack>
#include <cstdlib>
#define INF (1<<30)
using namespace std;int N,M;
char maze[105][105];
bitset<513> vis_keys[105][105];
bitset<33> vis_snakes[105][105];
int ans=INF;
int Kx,Ky,k;
int keys[]={0,1,3,7,15,31,63,127,255,511};
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};struct Node{int x,y,snakes,keys,step;bool operator<(const Node& o) const{return step>o.step;}
};struct snake{int x,y;
} snakes[5];
Node tmp;int bfs(){priority_queue<Node> q;q.push({Kx,Ky,0,0,0});while(q.size()){tmp=q.top();q.pop();for(int i=0;i<4;i++){int x0=tmp.x+dx[i];int y0=tmp.y+dy[i];if(x0<0 || y0<0 || x0>=N || y0>=N || maze[x0][y0]=='#') continue;if(vis_keys[x0][y0][tmp.keys]==1 && vis_snakes[x0][y0][tmp.snakes]==1) continue;int nsnakes=tmp.snakes,nkeys=tmp.keys,nstep=tmp.step+1;if(isdigit(maze[x0][y0])){int m=maze[x0][y0]-'0';if(m==1 || (nkeys>>(m-2)) & 1){nkeys |= (1<<(m-1));}}else if(maze[x0][y0]=='S'){int index=0;for(int i=0;i<k;i++){if(snakes[i].x==x0 && snakes[i].y==y0){index=i;break;}}if(!((nsnakes>>index) & 1)){nsnakes |=(1<<index);nstep +=1;}}else if(maze[x0][y0]=='T' && nkeys==keys[M]){return nstep;}q.push({x0,y0,nsnakes,nkeys,nstep});vis_keys[x0][y0][nkeys]=1;vis_snakes[x0][y0][nsnakes]=1;}}return -1;
}int main(){while(scanf("%d%d",&N,&M)!=EOF){if(N==0 && M==0) break;memset(vis_keys,0,sizeof(vis_keys));memset(vis_snakes,0,sizeof(vis_snakes));k=0;ans=1<<30;for(int i=0;i<N;i++)for(int j=0;j<N;j++){scanf(" %c",&maze[i][j]);if(maze[i][j]=='K'){Kx=i;Ky=j;}else if(maze[i][j]=='S'){snakes[k++]={i,j};}}ans=bfs();if(ans==-1){printf("impossible\n");}else{printf("%d\n",ans);}}return 0;
}

这篇关于[状态压缩 广搜BFS]Saving Tang Monk的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1081173

相关文章

多源 BFS

例题一 解法(bfs)(多个源头的最短路问题) 算法思路: 对于求的最终结果,我们有两种⽅式: • 第⼀种⽅式:从每⼀个 1 开始,然后通过层序遍历找到离它最近的 0 。 这⼀种⽅式,我们会以所有的 1 起点,来⼀次层序遍历,势必会遍历到很多重复的点。并且如果 矩阵中只有⼀个 0 的话,每⼀次层序遍历都要遍历很多层,时间复

模型压缩综述

https://www.cnblogs.com/shixiangwan/p/9015010.html

HTTP状态码中301与302的区别

一.官方说法  301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于:  301 redirect: 301 代表永久性转移(Permanently Moved)。  302 redirect: 302 代表暂时性转移(Temporarily Moved )。  这是很官方的说法,那么它们的区别到底是什么呢?  1.1、什么是301转向?什么是301重定向?

Zustand 状态管理库简介

1. Zustand 简介 Zustand(德语中意为“状态”)是一个使用简单 API 的 React 状态管理库。它的核心思想是以状态切片(slices)的方式组织应用状态,从而实现高效的状态管理。Zustand 提供了比 Redux 更加简洁和直接的用法,同时支持异步操作和中间件。 在React开发中,状态管理是一个非常重要的概念。虽然 React 提供了 useState 和 useRe

ESP32使用按键配网并通过LED指示网络状态

前言 上面我们已经可以通过 ESPTOUCH 和 Airkiss 给模块配网,并且存储在 nvs 中,重启后仍然可以联网,只是这样仍然不能满足我们实际的应用,这次我们增加按键作为输入,LED作为输出,实现长按按键配网,并可以通过LED指示网络状态。 添加自己的组件 为了让程序结构更加清晰,所以我们在smart_config例程的基础上做了修改,在main文件夹里新建了main.c 、smar

vue项目开启Gzip压缩配置方法及性能优化建议

原文地址:https://jingyan.baidu.com/album/454316ab29d0c0f7a7c03a1f.html?picindex=1   vue 项目开启gzip压缩和部署 nginx 开启gzip优化性能   第一步,在vue项目中安装依赖并将productionGzip改为true,开启Gzip压缩: npm install --save-dev compres

批量压缩文件夹内文件并记录解压密码

主要功能是: 遍历指定目录中的所有文件。 为每个文件生成一个随机密码。 使用生成的密码将文件压缩为 7z 格式。 将文件名和对应的密码记录到 passwords.txt 文件中。 import osimport randomimport stringfrom py7zr import SevenZipFile, exceptions# 设置文件夹路径folder_path = r'D:

BFS:解决多源最短路问题

文章目录 什么是多源最短路问题?1.矩阵2.飞地的数量3.地图的最高点4.地图分析总结 什么是多源最短路问题? 多源最短路问题(Multi-Source Shortest Path Problem,MSSP)是图论中的一个经典问题,它的目标是在给定图中找到从多个源点到所有其他顶点的最短路径。这个问题可以视为单源最短路问题(Single-Source Shortest Pa

20240621日志:大模型压缩-从闭源大模型蒸馏

目录 1. 核心内容2. 方法2.1 先验估计2.2 后验估计2.3 目标函数 3. 交叉熵损失函数与Kullback-Leibler(KL)损失函数 location:beijing 涉及知识:大模型压缩、知识蒸馏 Fig. 1 大模型压缩-知识蒸馏 1. 核心内容 本文提出在一个贝叶斯估计框架内估计闭源语言模型的输出分布,包括先验估计和后验估计。先验估计的目的是通

首次使用回声状态网络 (ESN) 和语音特征进行帕金森病 (PD) 预测

帕金森病(Parkinson's disease, PD)是一种使人衰弱的神经退行性疾病,它需要进行精确和早期的诊断,以便为患者提供有效的治疗和护理。这种疾病是由James Parkinson在1817年首次确定的,其特征是多巴胺生成神经元的退化。多巴胺的不足导致了一系列症状,包括静止性震颤、肌肉僵硬、运动迟缓(姿势不稳定)、以及其他重要特征,如睡眠障碍、心律失常、便秘和语音变化,这