第46届icpc 沈阳 J-Luggage Lock(思维 + 爆搜)

第46届icpc 沈阳 J-Luggage Lock(思维 + 爆搜)


题目来源:第46届icpc 沈阳 J-Luggage Lock


题意:

给出两个四位数的密码锁a和b, 求由a变到b所需的最小步数


思路:

  • 我们首先可以先将 a 变为 0000, 那么如果将 b 与 a 对应的位置旋转相同的次数, 那么 原始a -> 原始b 就等价于 0000 -> 修改后的b

    • 比如 0003 -> 0005 可以转换成 0000 -> 0002, 1234 -> 4321 可以转换成 0000 -> 3197
  • 我们记 c 为修改后的b, 那么此时我们就将 a -> b 转换成了 0000 -> c, 对于 c 我们会发现它最多有 10000 种状态, 所以此时我们可以直接爆搜

  • 每次搜的时候将当前状态从0000到当前状态所需的最小步数记录下来即可, 每次存储当前状态只用 1 步就能到达的状态.

那么怎么找当前状态只用一步就到的状态呢?

  • 因为每次移动需要是连续的, 所以不难发现, 最多有20种情况, 我们存入一个string字符串中, '1’表示修改当前位, '0’表示不修改, 再加上向上和向下是一样的(传一个参数 1 或者 -1, 用来记录是向上还是向下), 所以我们只需要存一遍即可 : 1000, 0100, 0010, 0001, 1100, 0110, 0011, 1110, 0111, 1111

AC代码

#include <bits/stdc++.h>
#define endl "\n"
#define rep(i, m, n) for (int i = (m); i <= (n); ++i)
#define rrep(i, m, n) for (int i = (m); i >= (n); --i)
#define IOS ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<string, int> PII;
const int N = 1e4 + 10, mod = 1e9 + 7;
int n, x[N]; // 记录 0000 到 i 需要的最小步数
bool vis[N]; // 记录状态是否访问过
string sss[] = { // 20种操作
	"1000", "0100", "0010", "0001",
	"1100", "0110", "0011", "1110",
	"0111", "1111"
};
// 对状态s进行第idx种操作, c = 1 / -1, 记录是向上还是向下旋转
string change(string s, int idx, int c) { 
	string t = s;
	for (int i = 0; i < 4; ++i)
		if (sss[idx][i] == '1')
			t[i] = (t[i] - '0' + c + 10) % 10 + '0';
	return t;
}
void init() {
	queue<PII> q; q.push({ "0000", 0 }); vis[0] = 1; // 推入起点
	while (!q.empty()) {
		auto t = q.front(); q.pop();
		string s = t.first; int cnt = t.second;
		for (int i = 0; i < 10; ++i) {
			string p1 = change(s, i, 1);
			string p2 = change(s, i, -1);
			int a1 = stoi(p1), a2 = stoi(p2); // 字符串转换成数字
			if (!vis[a1]) vis[a1] = 1, x[a1] = cnt + 1, q.push({ p1, cnt + 1 });
			if (!vis[a2]) vis[a2] = 1, x[a2] = cnt + 1, q.push({ p2, cnt + 1 });
		}
	}
}
void solve() {
	string a, b; cin >> a >> b;
	string t = "0000";
	for (int i = 0; i < 4; ++i)
		t[i] = (b[i] - a[i] + 10) % 10 + '0';
	printf("%d\n", x[stoi(t)]);
}
int main() {
	init();
	int t; cin >> t;
	while (t--) solve();
	return 0;
}

END

上一篇:ICPC:德才论


下一篇:2021 icpc 沈阳游记