Silly_3kidZ

思至水穷处,码看云起时

2021 ICPC 沈阳 J Luggage Lock

链接:

vJudge

题意:

有一个4位数字的密码锁,一次操作你可以选择连续的若干位同时向上或向下旋转一位,现问你从一个状态变换到另一个状态的最少操作次数

思路:

  1. 化繁为简,首先可以想到把所有的 a0a1a2a3>b0b1b2b3 转换为 0000>c0c1c2c3,其中 c0c1c2c3a0a1a2a3>b0b1b2b3 每一位数字正向(或逆向)移动的次数
  2. 宏观来看,我们要求的是 0000>00009999,本质上是一个单源最短路模型,且每条边边权为1,可以用 BFS 求解【这里没想到,没有宏观抽象出来看,抓着每一次状态用自己假想的贪心做法来写,浪费了很多时间】

code

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define DEBUG
#define debug(x) cerr << #x << " = " << x << "\n";
using db = long double;
using ll = long long;
// head
// 每个状态有20种移动方式
int d[20][4] = {
	{0, 0, 0, 1},
	{0, 0, 1, 0},
	{0, 1, 0, 0},
	{1, 0, 0, 0},
	{0, 0, 1, 1},
	{0, 1, 1, 0},
	{1, 1, 0, 0},
	{0, 1, 1, 1},
	{1, 1, 1, 0},
	{1, 1, 1, 1},
	{0, 0, 0, -1},
	{0, 0, -1, 0},
	{0, -1, 0, 0},
	{ -1, 0, 0, 0},
	{0, 0, -1, -1},
	{0, -1, -1, 0},
	{ -1, -1, 0, 0},
	{0, -1, -1, -1},
	{ -1, -1, -1, 0},
	{ -1, -1, -1, -1},
};
// dist数组存最短路
unordered_map<string, int> dist;
void bfs() {
	queue<string> q;
	q.push("0000");
	dist["0000"] = 0;
	while (!q.empty()) {
		auto t = q.front();
		q.pop();
		for (int i = 0; i < 20; i++) {
			string tmp = "0000";
			for (int j = 0; j < 4; j++) {
				tmp[j] = (t[j] - '0' + d[i][j] + 10) % 10 + '0';
			}
			// debug(tmp);
			if (!dist.count(tmp)) {
				dist[tmp] = dist[t] + 1;
				q.push(tmp);
			}
			// debug(dist[tmp]);
		}
	}
}
void solve() {
	string s1, s2;
	cin >> s1 >> s2;
	string s = "0000";
	// 0000 -> C0C1C2C3
	for (int i = 0; i < 4; i++) {
		s[i] = (s2[i] - s1[i] + 10) % 10 + '0';
	}
	// debug(s);
	cout << dist[s] << "\n";
}
int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); // debug调试注释,提交代码要有
	bfs();
	int T = 1; cin >> T;
	for (int cases = 1; cases <= T; cases++) {
		solve();
	}
	return 0;
}
posted @   Silly_3kidZ  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示