1 条题解
-
0
题目大意
有一个 的网格海滩,每个格子可能是:
- 半张日光浴床:
L(左半)、R(右半)、U(上半)、D(下半),它们与相邻的另一个半张组成一张完整的床; - 空地
.; - 障碍物
#。
一次操作可以移动一张完整的床,操作有两种:
- 旋转:抓住床的一边将其旋转 ,一半留在原地,另一半转到相邻的空格,代价为 ;
- 平移:沿床的长边移动一格,代价为 。
任何时候每张床占据两个相邻的空格。你可以进行多次操作,但不能同时移动多张床。
目标是为 Andrew 腾出两个相邻的空格用来放置他的床。求最小的总不适感代价;若不可能,输出 。数据范围
,,。
题解
1. 棋盘染色与视角转换
对网格进行黑白棋盘染色(相邻格子颜色不同)。因为每张床总是占据两个相邻格子,所以必然占据一个黑格和一个白格。
关键转换:不看作移动床,而是看作移动空格。
床的一次操作对应一个空格沿着床的某条边“跳”到另一个格子,且空格始终不改变所在格子的颜色。
例如,一张水平床(L在 ,R在 ),如果绕左半 旋转,右半会移动到 或 ,要求该格为空。从空格的角度看:原先在 的空格会移动到 ,同时 被床占据。最终需要两个相邻空格,它们必然一黑一白。问题变成:从初始的所有空格出发,每次通过操作某张床使空格移动(代价 或 ),最终让两个相邻异色格子都变为空格的最小总代价。
2. 建图
我们将每个非障碍格子看作图的一个结点,并在它们之间连有向边,表示空格的一次可能移动。
对每一张初始的床,根据其类型添加边:
设床占据的两个格子为 和 (相邻且颜色不同)。用 或 表示操作代价。
-
水平床: 左
L在 ,右R在 。- 旋转(代价 ):
绕L旋转 空格从 或 移动到 ;
绕R旋转 空格从 或 移动到 。 - 平移(代价 ):
向左平移(长边方向) 空格从 移动到 ;
向右平移 空格从 移动到 。
- 旋转(代价 ):
-
垂直床: 上
U在 ,下D在 。- 旋转(代价 ):
绕U旋转 空格从 或 移动到 ;
绕D旋转 空格从 或 移动到 。 - 平移(代价 ):
向上平移 空格从 移动到 ;
向下平移 空格从 移动到 。
- 旋转(代价 ):
以上所有移动的起点、终点必须在网格内且不是
#。这样构建出的有向图中,每一条边恰好对应某一特定床的一次操作。
可以证明:在最优方案中,每张床最多被操作一次,因此图上的任何路径自然满足每张床至多使用一次(床被使用后位置改变,不会再产生原图的其他边)。3. 多源最短路(Dijkstra)
将所有初始空地
.作为源点,距离设为 ;其他格子距离设为 。
在上述有向图上运行 Dijkstra 算法,得到每个格子 的距离 ,表示将该格子变为空地所需的最小不适感代价。4. 计算答案
枚举所有相邻的格子对 (上下左右相邻),如果它们颜色不同(棋盘染色),且 和 都不是 ,则用 更新答案。
若不存在任何满足条件的相邻对,输出 ;否则输出最小总代价。
5. 复杂度分析
- 结点数:。
- 边数:每张床最多添加 条边,总边数 。
- Dijkstra 使用优先队列:。
- 总复杂度:,足以通过。
参考代码框架(略,按照上述建图与 Dijkstra 实现即可)
- 半张日光浴床:
- 1
信息
- ID
- 7187
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者