Uva 101 The Blocks Problem(模拟)
题目链接:https://vjudge.net/problem/UVA-101
题意
有 0 ~ n - 1 个木块,一共有四种指令:
- move a onto b:把 a 和 b 上方的木块全部复位,然后把 a 放在 b 上面。
- move a over b:把 a 上方的木块全部复位,然后把 a 放在 b 所在的木块堆顶部。
- pile a onto b:把 b 上方的木块全部复位,然后把 a 及上面的木块整体放在 b 上面。
- pile a over b:把 a 及上面的木块整体放在 b 所在的木块堆的顶部。
如果 a b 在同一木块堆中则视为无效指令。
思路
从四种指令中抽象出两个基本操作:
- clear above:把 a 上方的木块全部复位
- move:把 a 以及上方的木块放在 b 所在木块堆的顶部
然后考虑如何快速查找某一木块所在的木块堆以及在其中的高度,可以用一个一对二的映射,将每个木块推入新堆时更新。
代码
初始代码
#include <bits/stdc++.h> using namespace std; vector<vector<int>> v; map<int, pair<int, int>> mp; void update(int a, int b) {//把 b 推入木块堆 a 中的同时更新其所在的木块堆和高度 mp[b].first = a; mp[b].second = v[a].size(); v[a].push_back(b); } void clear_above(int a) {//将 a 上面的木块复位 int vec = mp[a].first; int h = mp[a].second; for (int i = h + 1; i < v[vec].size(); i++) { update(v[vec][i], v[vec][i]); } v[vec].resize(h + 1); } void move(int a, int b) {//将 a 以及 a 上面的木块放在 b 所在木块堆顶部 int vec = mp[a].first; int h = mp[a].second; int vec_b = mp[b].first; for (int i = h; i < v[vec].size(); i++) { update(vec_b, v[vec][i]); } v[vec].rresize(h); } int main() { int n; cin >> n; v.resize(n); for (int i = 0; i < n; i++) update(i, i); string s1; while (cin >> s1 and s1 != "quit") { int a, b; string s2; cin >> a >> s2 >> b; if (mp[a].first == mp[b].first) continue; if (s1 == "move") { if (s2 == "onto") {//move_onto clear_above(a); clear_above(b); move(a, b); } else {//move_over clear_above(a); move(a, b); } } else { if (s2 == "onto") {//pile_onto clear_above(b); move(a, b); } else {//pile_over move(a, b); } } } for (int i = 0; i < n; i++) { cout << i << ":"; for (int x : v[i]) cout << ' ' << x; cout << "\n"; } }
优化
不难发现:
- s1 为 “move” 时有 clear_above(a)
- s2 为 "onto" 时有 clear_above(b)
- 四种指令都有 move(a, b)
优化代码
#include <bits/stdc++.h> using namespace std; vector<vector<int>> v; map<int, pair<int, int>> mp; void update(int a, int b) {//把 b 推入木块堆 a 中的同时更新其所在的木块堆和高度 mp[b].first = a; mp[b].second = v[a].size(); v[a].push_back(b); } void clear_above(int a) {//将 a 上面的木块复位 int vec = mp[a].first; int h = mp[a].second; for (int i = h + 1; i < v[vec].size(); i++) { update(v[vec][i], v[vec][i]); } v[vec].resize(h + 1); } void move(int a, int b) {//将 a 以及 a 上面的木块放在 b 所在木块堆顶部 int vec = mp[a].first; int h = mp[a].second; int vec_b = mp[b].first; for (int i = h; i < v[vec].size(); i++) { update(vec_b, v[vec][i]); } v[vec].resize(h); } int main() { int n; cin >> n; v.resize(n); for (int i = 0; i < n; i++) update(i, i); string s1; while (cin >> s1 and s1 != "quit") { int a, b; string s2; cin >> a >> s2 >> b; if (mp[a].first == mp[b].first) continue; if (s1 == "move") clear_above(a); if (s2 == "onto") clear_above(b); move(a, b); } for (int i = 0; i < n; i++) { cout << i << ":"; for (int x : v[i]) cout << ' ' << x; cout << "\n"; } }

浙公网安备 33010602011771号