101 - The Blocks Problem

Problem.png

以题中的10块木块为例,即有10个位置,一开始从0到9依次放在10个位置上,然后机器人执行输入的指令,move a onto b 就是把a号和b号块上叠放着的的所有块归位(即0回到0位置,1回到1位置,依次类推),然后把a放到b上(a紧贴着b所以是onto),pile a onto b 就是把a和a上放着的所有块一起放在b上(紧贴着),move a over b就是把a上放着的所有块归位,然后直接放在b那堆上(不用紧贴b),pile a over b 意义类推。注意a和b在同一堆的话为无效指令,直接跳过不执行。
因此本题就是要模拟移动木块的过程,每个木块堆中木块的数目不确定,即每堆的高度不确定,所以可以用一个vector来保存一个木块堆,而木块堆的个数不超过N,所以可以用一个数组来保存所有堆,因此最后使用了vector的数组来组织数据。
接下来就是模拟各种操作,其实仔细分析后可以发现,四种命令全是由两种操作组成:

  1. 将块a上的所有块归位
  2. 把块a和a上的所有块都叠放到块b所在的那一堆

可以分别写成两个函数。
当然首先要根据指令找到块a和块b的位置,哪一堆哪一块。因为需要两个值来定位一个块,所以寻找块位置的函数需要使用引用作为参数来返回值。
然后移动块的操作可以用各种pop_back()和push_back()还有一个栈辅助完成,注意栈的top()函数的返回值是引用,直接把返回值作为push_back等其他函数的参数会出错,得用一个临时变量存储返回值(好像不仅是top会这样,所以push_back的参数都用临时变量来传就好了)。而pop_back()返回值为空,因此要先用下标获取vector的最后一个值然后再pop_back()。

但是,上面这种方法其实是麻烦了。。看了书才发现可以用下标索引把(例如b块)之上的块都push_back到另一个堆尾部,然后对原来的堆直接调用resize()调整大小,只保留下标0~b块,后面的块丢掉就行了,真是简单粗暴。。

要点:
以引用作为参数使函数可以返回多个值。
vector的用法,push_back,pop_back,resize,size等函数的灵活运用。
把每项具体的功能抽象为一个函数,使程序逻辑清晰。

#include <iostream>
#include <string>
#include <vector>
#include <stack>

using namespace std;

const int maxn = 26;

int N;

vector<int> pile[maxn];

void find_pos(int num, int& p, int& h) {
    for (p = 0; p < N; p++) {
        for (h = 0; h < pile[p].size(); h++) {
            if (pile[p][h] == num) return;
        }
    }
}

void clear_above(int p, int h) {
    for (int i = pile[p].size() - 1; i > h; i--) {
        int num = pile[p][pile[p].size() - 1];
        pile[p].pop_back();
        pile[num].push_back(num);
    }
}

void pile_over(int pa, int ha, int pb, int hb) {
    stack<int> s;
    for (int i = pile[pa].size() - 1; i >= ha; i--) {
        int num = pile[pa][pile[pa].size() - 1];
        pile[pa].pop_back();
        s.push(num);
    }
    while (!s.empty()) {
        int top_num = s.top();
        pile[pb].push_back(top_num);
        s.pop();
    }
}

void print_pile() {
    for (int i = 0; i < N; i++) {
        if (pile[i].empty()) {
            cout << i << ':' << endl;
        }
        else {
            cout << i << ':';
            for (int j = 0; j < pile[i].size(); j++) {
                cout << ' ' << pile[i][j];
            }
            cout << endl;
        }
    }
}

int main() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        pile[i].push_back(i);
    }
    while (1) {
        string cmd1, cmd2;
        int a, b;
        cin >> cmd1;
        if (cmd1 == "quit") break;
        cin >> a >> cmd2 >> b;
        int pa, ha, pb, hb;
        find_pos(a, pa, ha);
        find_pos(b, pb, hb);
        if (pa == pb) continue;
        if (cmd1 == "move" && cmd2 == "onto") {
            clear_above(pa, ha);
            clear_above(pb, hb);
            pile_over(pa, ha, pb, hb);
        }
        else if (cmd1 == "move" && cmd2 == "over") {
            clear_above(pa, ha);
            pile_over(pa, ha, pb, hb);
        }
        else if (cmd1 == "pile" && cmd2 == "onto") {
            clear_above(pb, hb);
            pile_over(pa, ha, pb, hb);
        }
        else if (cmd1 == "pile" && cmd2 == "over") {
            pile_over(pa, ha, pb, hb);
        }
    }
    print_pile();
    return 0;
}

上面是我的代码,然而还是汝佳巨牛写的代码简洁优雅。。见书P110~111

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容