The Blocks Problem

发布时间:2024年01月18日

本题是一道模拟题,但个人感觉挺有意思的(思路很明确,但是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 0n?1,要求实现下列四种操作:

  1. move a onto b : 把 a a a b b b 上方的木块归位,然后把 a a a 放到 b b b 上面。
  2. move a over b : 把 a a a 上方的木块归位,然后把 a a a 放在 b b b 所在木块堆的最上方。
  3. pile a onto b : 把 b b b 上方的木块归位,然后把 a a a 及以上的木块坨到 b b b 上面。
  4. 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 second

const 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) {
    IOS

    int ALL = 1; 
    // cin >> ALL;
    while(ALL -- ) Solved();
    // cout << fixed;//强制以小数形式显示
    // cout << setprecision(n); //保留n位小数

    return 0;
}
文章来源:https://blog.csdn.net/weixin_73523694/article/details/135685050
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。