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

NOIP2013提高组.华容道

题目

509. 华容道
在这里插入图片描述

算法标签: 搜索, b f s bfs bfs, s p f a spfa spfa

思路

不难发现, 在人移动的过程中, 箱子是不动的, 从当前位置到下一个箱子旁边的位置不会移动箱子, 可以预处理出人在每个位置到其他位置的距离预处理, 从某一个状态出发, 走到另一个状态的最短路使用 s p f a spfa spfa算法, 一般来说时间复杂度 O ( m ) O(m) O(m), 极端情况下时间复杂度 O ( n m ) O(nm) O(nm)

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 35, M = 3610, K = M * 4, INF = 0x3f3f3f3f;
const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int n, m, q, g[N][N];
vector<PII> head[M];
int d1[N][N], d2[M];
bool vis[M];

void add(int u, int v, int w) {
	head[u].push_back({v, w});
}

int get(int x, int y, int z) {
	return ((x - 1) * m + y - 1) * 4 + z;
}

void bfs(int px, int py, int bx, int by, int dir) {
	queue<PII> q;
	memset(d1, 0x3f, sizeof d1);
	d1[px][py] = d1[bx][by] = 0;
	q.push({px, py});

	while (!q.empty()) {
		auto [x, y] = q.front();
		q.pop();

		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (g[x][y] && d1[x][y] + 1 < d1[nx][ny]) {
				d1[nx][ny] = d1[x][y] + 1;
				q.push({nx, ny});
			}
		}
	}

	if (dir == -1) return;

	int u = get(bx, by, dir);
	for (int i = 0; i < 4; ++i) {
		if (i == dir) continue;
		int nx = bx + dx[i], ny = by + dy[i];
		if (d1[nx][ny] < INF) {
			add(u, get(bx, by, i), d1[nx][ny]);
		}
	}

	// 搬运到对立面的箱需要1的花费
	add(u, get(px, py, dir ^ 2), 1);
}

int spfa(int sx, int sy, int tx, int ty) {
	queue<int> q;
	memset(d2, 0x3f, sizeof d2);

	for (int i = 0; i < 4; ++i) {
		int nx = sx + dx[i], ny = sy + dy[i];
		if (d1[nx][ny] < INF) {
			int u = get(sx, sy, i);
			d2[u] = d1[nx][ny];
			q.push(u);
			vis[u] = true;
		}
	}

	while (!q.empty()) {
		auto u = q.front();
		q.pop();
		vis[u] = false;

		for (auto [v, w] : head[u]) {
			if (d2[u] + w < d2[v]) {
				d2[v] = d2[u] + w;
				if (!vis[v]) {
					q.push(v);
					vis[v] = true;
				}
			}
		}
	}

	int ans = INF;
	for (int i = 0; i < 4; ++i) {
		ans = min(ans, d2[get(tx, ty, i)]);
	}
	if (ans == INF) ans = -1;
	return ans;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	cin >> n >> m >> q;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cin >> g[i][j];
		}
	}

	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (g[i][j]) {
				// 枚举人的位置
				for (int k = 0; k < 4; ++k) {
					int nx = i + dx[k], ny = j + dy[k];
					if (g[nx][ny]) bfs(nx, ny, i, j, k);
				}
			}
		}
	}

	while (q--) {
		int ex, ey, sx, sy, tx, ty;
		cin >> ex >> ey >> sx >> sy >> tx >> ty;
		if (sx == tx && sy == ty) cout << 0 << "\n";
		else {
			// 现将人移动到箱子周围
			bfs(ex, ey, sx, sy, -1);
			// 再从箱子周围的状态转移到最终状态
			int ans = spfa(sx, sy, tx, ty);
			cout << ans << "\n";
		}
	}

	return 0;
}
http://www.dtcms.com/a/112050.html

相关文章:

  • 从菜鸟到高手的提示词优化指南‌
  • Muduo网络库介绍
  • Sensodrive力控关节模组SensoJoint:TÜV安全认证助力机器人开发
  • 主机和虚拟机间的网络通信
  • LeetCode算法题(Go语言实现)_29
  • JavaScript重难点突破:事件循环
  • 基于 Python 的自然语言处理系列(70):检索增强生成(RAG)
  • Go语言-初学者日记(八):构建、部署与 Docker 化
  • 《操作系统真象还原》第五章(2)——启用内存分页机制
  • 蓝桥杯15届 宝石组合
  • 【HC-05蓝牙模块】基础AT指令测试
  • 思维链 Chain-of-Thought(COT)
  • 视野,,地面覆盖,重叠需求,FPS,飞行速度等的计算公式
  • LLM面试题五
  • JVM 有哪些垃圾回收器
  • 【2023】ORIGIN或MATLAB 颜色图,等高图,颜色条——需要拟合补全中间的颜色
  • 算法--最长上升子序列
  • 京东零售首次公开!6B参数时序大模型实现20000款商品自动补货预测
  • Java 搭建 MC 1.18.2 Forge 开发环境
  • 《探索边缘计算:重塑未来智能物联网的关键技术》
  • agent 入门
  • ARM-外部中断,ADC模数转换器
  • Vue3学习二
  • 【Node】一文掌握 Express 的详细用法(Express 备忘速查)
  • 【面试篇】Mysql
  • DHCP之中继 Relay-snooping及配置命令
  • Python_level1_字符串_11
  • 给项目中的用户头像,添加用户的历史头像记录功能
  • 深入理解SQL中的<>运算符:不等于的灵活运用
  • C++20的协程简介