本题是一道模拟题,但个人感觉挺有意思的(思路很明确,但是WA了好几发才过),因此来讲一讲思路。
题面
题面PDF
样例输入
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit
样例输出
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:
题意简述
初始时从左到右有 n n n 个木块,编号分别为 0 … n − 1 0 \ldots n-1 0…n−1,要求实现下列四种操作:
move a onto b
: 把 a a a 和 b b b 上方的木块归位,然后把 a a a 放到 b b b 上面。move a over b
: 把 a a a 上方的木块归位,然后把 a a a 放在 b b b 所在木块堆的最上方。pile a onto b
: 把 b b b 上方的木块归位,然后把 a a a 及以上的木块坨到 b b b 上面。pile a over b
: 把 a a a 及以上的木块坨到 b b b 的上面。
一组数据的结束标志为
quit
,如果有非法指令(如 a a a 与 b b b 在同一堆),无需处理。
输出:所有操作输入完毕后,从左到右,从下到上输出每个位置的木块编号。
思路
通过观察上面四种操作,我们会发现,这四种操作可以拆分为三种:
- move x x x:将木块x上面木块归位。
- pile x x x:无操作。
- onto x x x:将木块x上面的木块归位。
- over x x x:无操作。
然后我们还会发现,无论哪个操作,最终都会将a放在b上边。
因此,上边的操作就转换为了两类:归位和合并。然后我们实现这两种操作即可。
而这两种操作显然用 v e c t o r vector vector容器比较方便,因此我们尝试用 v e c t o r vector vector来实现。标程里有详细代码+注释,请放心食用。
标程
#include<bits/stdc++.h>using namespace std;#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
#define LL long long
#define ULL unsigned long long
#define PII pair<int, int>
#define lowbit(x) (x & -x)
#define Mid ((l + r) >> 1)
#define ALL(x) x.begin(), x.end()
#define endl '\n'
#define fi first
#define se secondconst int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;vector<vector<int>> a(30); //用二维vector,第一维表示原位置,第二维表示当前位置堆的木块
int n, x1, x2;PII find(int x) { //找到需要进行操作的木块的位置for(int i = 0; i < n; i ++ )for(int j = 0; j < a[i].size(); j ++ )if(a[i][j] == x) return {i, j}; //第i堆的第j个
}void homing(PII i) { //归位操作while(a[i.fi].size() - 1 > i.se) {int t = a[i.fi].back();a[t].push_back(t); //将其后边的全都归位,本身不动a[i.fi].pop_back();}
}void merge(PII i, PII j) { //合并操作for(int k = i.se; k < a[i.fi].size(); k ++ ) {int t = a[i.fi][k];a[j.fi].push_back(t);}a[i.fi].resize(i.se); //将其大小设为i.se,相当于舍弃后面的元素
}void Solved() {cin >> n;string s1, s2;for(int i = 0; i < n; i ++ ) a[i].push_back(i);//初始化while(cin >> s1) {if(s1 == "quit") break;cin >> x1 >> s2 >> x2;PII y1 = find(x1), y2 = find(x2); //如果在同一堆的话是没办法进行操作的if(y1.fi == y2.fi) continue;if(s2 == "onto") homing(y2); //需要先对b进行操作if(s1 == "move") homing(y1);merge(y1, y2);}for(int i = 0; i < n; i ++ ) {//输出cout << i << ":";for(int j : a[i]) cout << " " << j;cout << endl;}
}signed main(void) {IOSint ALL = 1; // cin >> ALL;while(ALL -- ) Solved();// cout << fixed;//强制以小数形式显示// cout << setprecision(n); //保留n位小数return 0;
}