当前位置: 首页 > news >正文

UVa 360 Don‘t Get Hives From This One

题目描述

Billy Bee\texttt{Billy Bee}Billy Bee想利用蜂巢的一个废弃楼层作为“趣味迷宫”。他将出售门票赚大钱。下面的示例是“矩形”的,有111111121212列。Billy\texttt{Billy}Billy的迷宫也将是矩形的,形状类似,但尺寸可能不同。单元格按所示模式用数字序列标识(从111开始)。迷宫的特点是许多相邻单元格之间有开口。还有两个通向外部开口:入口和出口。

单元格的朝向如图所示(水平边和斜边,但没有垂直边)。迷宫的第二行从第一个房间的右下侧开始。

Billy\texttt{Billy}Billy已经布置好了迷宫,但他不太聪明,自己解不出来。他雇你来帮他找到一条穿过迷宫的路径。你决定使用著名的右手法则编写计算机程序来解决这种“矩形六边形迷宫”,并向Billy Bee\texttt{Billy Bee}Billy Bee收取开发费用。

右手法则:当你进入一个平面迷宫时,将右手放在入口的墙上,然后向前走,手始终不离开墙壁,最终你会从出口门离开迷宫(如果出口不可达,你会从入口门离开)。

输入格式

输入文件包含零个或多个迷宫描述,紧随其后。

每个迷宫描述的第一行包含两个正整数rrrcccr≤30,c≤30r \leq 30, c \leq 30r30,c30),用空格分隔,分别表示迷宫的行数和列数。或者,该行可能只包含两个零(空格分隔),表示没有更多迷宫需要读取和求解。

每个迷宫描述的第二行也包含两个正整数,用空格分隔,表示迷宫入口的房间号和墙壁编号。(每个房间的墙壁按顺时针方向编号,从顶墙=1=1=1开始。)

第三行以相同方式标识迷宫出口的房间号和墙壁编号。入口和出口是不同的门。

其余行每行描述迷宫中的一个房间。每行包含一个房间号,后面跟着111666个整数(每个在111666范围内),用单个空格分隔。房间号后面的整数表示有开口的墙壁编号,可以是任意顺序,行的顺序也可以是任意的。数据集中的房间不会重复。未在数据集中列出的房间没有门。

迷宫描述的结束由一行只包含整数0表示。这行之后要么开始下一个迷宫描述,要么包含表示数据结束的两个零。

输出格式

首先,程序应列出搜索过程中遇到的房间序列,每行最多202020个房间(最后一行可能少于202020),同行值之间用单个空格分隔。注意,最后一个列出的房间要么是出口房间(如果找到解),要么是入口房间(否则)。

其次,在搜索路径最后一行下面一行输出SOLUTION FOUNDNO SOLUTION,对应是否找到从入口到出口的路径。

样例输入

11 12 1 1 5 1 1 1 4 56 1 57 1 3 5 6 58 3 5 3 3 11 3 6 12 4 ... 0 0 0

样例输出

1 13 7 14 26 31 19 25 37 49 43 49 37 25 19 31 26 14 7 13 1 NO SOLUTION

题目分析

问题的本质

这是一个六边形网格迷宫的模拟问题。六边形网格的每个单元格有666个面(墙壁),编号111666顺时针。每个门(开口)位于两个相邻单元格之间的墙上。使用右手法则模拟从入口到出口的路径。

六边形网格的几何

与正方形网格不同,六边形网格有奇偶行差异:

  • 奇数行和偶数行的单元格偏移不同
  • 每个六边形有 6 个邻居(分别为北、东北、东南、南、西南、西北)

右手法则

当从某个方向进入一个房间时,右手法则要求:

  1. 将右手放在你进入时所经过的墙壁上
  2. 顺时针旋转(保持手在墙上),找到第一个有门的墙壁
  3. 通过那个门进入相邻房间
  4. 重复直到到达出口或回到入口

在代码中,这表现为:从进入时的墙壁号开始,逆时针查找(因为进入方向与墙壁方向的关系),找到第一个有开口的墙壁。

坐标映射

由于房间编号是连续的(1,2,3,…1, 2, 3, \dots1,2,3,),但六边形网格的几何结构复杂,需要使用一个映射表将逻辑房间号转换为网格坐标,以便确定相邻关系。

参考代码

// Don't Get Hives From This One!// UVa ID: 360// Verdict: Accepted// Submission Date: 2016-11-24// UVa Run Time: 0.000s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;// 墙壁编号对应关系:进入墙壁的对面intlink[10]={0,4,5,6,1,2,3};intstart,start_opening,dest,dest_opening;intdoor[1000][10];// 房间的墙壁开口信息intadjacent[1000][10];// 相邻房间编号intto_cell[1000];// 网格位置 → 房间号intto_number[1000];// 房间号 → 网格位置intenabled[1000];// 该网格位置是否存在boolfinished;// 是否完成搜索vector<int>sequences;// 路径序列// 右手法则 DFSvoiddfs(introom,intwall){if(finished)return;sequences.push_back(room);// 检查是否到达出口intnext_wall=wall;for(intk=1;k<=6;k++){next_wall--;if(next_wall<=0)next_wall+=6;if((room==to_number[start]&&next_wall==start_opening)||(room==to_number[dest]&&next_wall==dest_opening)){finished=true;return;}if(door[room][next_wall])break;}// 如果没有出口或邻居不存在,结束if(!adjacent[room][next_wall]||!enabled[adjacent[room][next_wall]]){finished=true;return;}// 进入相邻房间dfs(adjacent[room][next_wall],link[next_wall]);}// 将网格位置映射到房间号voidmap_cell_to_number(intr,intc){memset(to_cell,0,sizeof(to_cell));memset(to_number,0,sizeof(to_number));intoffset=c/2+c%2,base=0;for(inti=1;i<=r;i++){for(intj=1;j<=c;j++){if(j%2==1){to_cell[(i-1)*30+j]=base+(j+1)/2;to_number[base+(j+1)/2]=(i-1)*30+j;}else{to_cell[(i-1)*30+j]=base+j/2+offset;to_number[base+j/2+offset]=(i-1)*30+j;}}base+=c;}memset(enabled,0,sizeof(enabled));intcells=0;for(inti=1;i<=r;i++)cells+=(i%2==1)?((c+1)/2):(c/2);for(inti=1;i<=cells;i++)enabled[to_number[i]]=1;}// 初始化六边形网格的相邻关系voidinitialize(){intoffset[2][6]={{-30,1,31,30,29,-1},{-30,-29,1,30,-1,-31}};memset(adjacent,0,sizeof(adjacent));for(inti=1;i<=15;i++)for(intj=1;j<=30;j++){intnumber=(i-1)*30+j;for(intk=1;k<=6;k++)adjacent[number][k]=number+offset[j%2][k-1];// 边界处理if(i==1){adjacent[number][1]=0;if(j%2==1)adjacent[number][2]=adjacent[number][6]=0;}if(i==15){adjacent[number][4]=0;if(j%2==0)adjacent[number][3]=adjacent[number][5]=0;}if(j==1)adjacent[number][5]=adjacent[number][6]=0;if(j==30)adjacent[number][2]=adjacent[number][3]=0;}}intmain(){initialize();intr,c;string line;while(cin>>r>>c,r>0){// 映射房间号到网格位置map_cell_to_number(r,c);memset(door,0,sizeof(door));// 读取入口和出口cin>>start>>start_opening>>dest>>dest_opening;// 读取房间门信息introom,wall;while(cin>>room,room>0){getline(cin,line);istringstreamiss(line);while(iss>>wall)door[to_number[room]][wall]=1;}// 右手法则 DFSsequences.clear();finished=false;dfs(to_number[start],start_opening);// 输出路径for(inti=0;i<sequences.size();i++){cout<<to_cell[sequences[i]];if((i+1)==sequences.size()||(i+1)%20==0)cout<<'\n';elsecout<<' ';}// 输出结果if(sequences.back()==to_number[dest])cout<<"SOLUTION FOUND\n";elsecout<<"NO SOLUTION\n";}return0;}
http://www.jsqmd.com/news/934568/

相关文章:

  • 别再死记硬背公式了!用NumPy手撸线性回归,从MSE、R²到梯度下降实战通关
  • 废旧笔记本屏幕改造外接显示器:从拆解到组装的完整DIY指南
  • 保姆级教程:用Python的NumPy和Matplotlib一步步拆解时间序列(含SSA算法完整代码)
  • 别再只用真彩色了!Landsat8这5个隐藏的波段组合,让你的遥感图瞬间出彩
  • 深圳黄金回收避坑榜单:2026上门品牌综合测评,收的顶不扣秤不压价首选 - 奢侈品回收测评
  • bili2text终极指南:免费视频转文字工具完整使用手册
  • ESP8266-01S连接阿里云MQTT:除了AT指令,你还需要注意这些硬件和网络“暗坑”
  • 亲测好用的降AI工具盘点,附免费AI查重方法 - 晨晨_分享AI
  • STM32CubeMX驱动TFT-LCD触摸屏:从模拟SPI到XPT2046校准的完整避坑指南
  • 别再只盯着Faster R-CNN了:食物热量估算实战,对比YOLOv8、DETR和MobileNet的精度与速度
  • 别再乱传code了!微信小程序获取手机号,后端C#解密完整流程(附避坑点)
  • 从三态门到总线竞争:用Verilog强度建模理解硬件电路的‘软’冲突
  • 如何快速使用Boss直聘批量投递助手:求职效率提升10倍的终极指南
  • Arduino超声波传感器与LED联动:从原理到实践的完整项目指南
  • 2026年深圳黄金回收多少钱一克?五家靠谱实体门店实测推荐 - 奢侈品回收测评
  • RISC-V仿真与硬件性能对比研究:FireSim框架实践
  • 数学建模小白也能搞定:用Python复现五一赛B题快递需求分析(附完整代码和Paper)
  • 2026深圳LV二手包包回收口碑排名,收的顶闭眼选不踩坑 - 奢侈品回收测评
  • 2026电钢琴键盘类型深度解析:+2026年6款高性价比机型推荐
  • 从5G基站到手机:聊聊Doherty、EER这些效率提升技术到底用在哪?
  • 给LinuxCNC RS274NGC解释器“打补丁”:手把手教你添加自定义G77车削循环
  • 告别打包噩梦:用虚拟环境+PyInstaller Hook干净利落地打包Paddle深度学习项目
  • 基于Arduino的JVS街机I/O板USB HID改造方案
  • SpringBoot课程管理系统毕业设计包:含可运行源码、MySQL建表脚本与全套毕设文档
  • 论文AI率过高难通过?亲测有效降AI工具指南 - 老米_专讲AIGC率
  • 从旋变芯片到伺服控制:AD2S1210在电机位置反馈中的实战配置指南
  • 高效研究周报撰写指南:从个人探索到团队知识管理
  • 手机号码定位系统:3分钟掌握地理信息查询的核心技术
  • 从CAD小白到建模高手:用OpenCASCADE 7.8.0一步步教你打造一个带螺纹的3D瓶子模型
  • 从零打造桌面电子时钟:Atmega328P硬件设计与Arduino固件开发全流程