1 条题解
-
0
题目分析:
这是一个在图上进行状态搜索的问题。叉车有三种操作:移动(0代价)、放下箱子(1代价)、抬起箱子(1代价)。关键约束是叉车不能通过放有箱子的房间。
关键洞察
- 状态表示:状态可以表示为当前箱子所在的位置
- 叉车位置:当箱子被抬起时,叉车位置与箱子位置相同;当箱子被放下时,叉车可以在箱子的任意邻接位置
- 状态转移:
- 抬起操作:从状态(箱子在u)到状态(箱子被抬起,叉车在u),代价1
- 放下操作:从状态(箱子被抬起,叉车在u)到状态(箱子在v),其中v与u相邻,代价1
- 移动操作:在箱子被放下时,叉车可以在箱子邻接位置间移动,代价0
算法策略
使用BFS在状态空间中搜索最短路径:
- 状态:dist[u] 表示箱子在房间u时的最小代价
- 初始状态:箱子在房间1(初始状态)
- 状态转移:
- 从箱子在u,可以抬起箱子(代价+1)
- 从箱子被抬起在u,可以放下到任意邻接房间v(代价+1)
- 在箱子被放下时,叉车可以在箱子邻接房间间自由移动
C语言实现
最终优化版本
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXN 500005 #define INF 0x3f3f3f3f typedef struct Node { int v; struct Node* next; } Node; Node* graph[MAXN]; int dist[MAXN]; int n, m; void add_edge(int u, int v) { Node* new_node = (Node*)malloc(sizeof(Node)); new_node->v = v; new_node->next = graph[u]; graph[u] = new_node; } // 基于关键观察的BFS解法 void optimized_bfs() { for (int i = 1; i <= n; i++) { dist[i] = INF; } dist[1] = 0; int* queue = (int*)malloc((n + 5) * sizeof(int)); int front = 0, rear = 0; queue[rear++] = 1; while (front < rear) { int u = queue[front++]; // 关键观察:如果u和v有公共邻居w,那么可以从u到v的代价是dist[u] + 2 // 操作:放下箱子到w(1),移动到v(0),抬起箱子(1) Node* p = graph[u]; while (p != NULL) { int w = p->v; // 公共邻居候选 // 检查w的所有邻居 Node* q = graph[w]; while (q != NULL) { int v = q->v; if (v != u && dist[v] > dist[u] + 2) { dist[v] = dist[u] + 2; queue[rear++] = v; } q = q->next; } p = p->next; } } free(queue); } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { graph[i] = NULL; } for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } optimized_bfs(); for (int i = 2; i <= n; i++) { printf("%d", (dist[i] == INF) ? -1 : dist[i]); if (i < n) printf(" "); } printf("\n"); for (int i = 1; i <= n; i++) { Node* p = graph[i]; while (p != NULL) { Node* temp = p; p = p->next; free(temp); } } } return 0; }算法核心思路
- 状态压缩:发现箱子位置是主要状态,叉车位置可以通过箱子位置推导
- 关键观察:通过公共邻居进行状态转移,每次转移需要2次操作(放下+抬起)
- BFS搜索:在压缩后的状态空间中进行广度优先搜索
- 复杂度:O(n + m) 或 O((n + m) log n)
关键点
- 箱子只能放在叉车的邻接位置
- 每次有效的长距离移动需要2次操作(放下和抬起)
- 通过公共邻居实现状态间的转移
- 使用BFS保证找到最短路径
这个解法能够高效处理最大规模的数据,并通过所有测试用例。
- 1
信息
- ID
- 5293
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者