uva 101

题目:给你n个方块,有四种操作:

            1.move a onto b,把a和b上面的方块都放回原来位置,然后把a放到b上面;

            2.move a over b,把a上面的放回原处,然后把a放在b所在的方块堆的上面;

            3.pile a onto b,把b上面的放回原来位置,然后把a和a上面的方块整体放到b上面;

            4.pile a over b,把a和a上面的方块整体放到b所在堆的上面。

分析:模拟,数据结构。观察操作,如果是move就是先把a上面的还原,如果是onto就是先把b上面的还原。

            然后,就是移动一堆到另一堆的上面(单个也认为是一堆)。所以设置两个基础操作:

            1.将a上面的还原init_pos(a);

            2.将a和上面的(可以没有上面的)放到b上面pile_over(a, b)。

            那么上述的四组操作就变成下面了:

            1.move a onto b,init_pos(a)init_pos(b)pile_over(a, b)

            2.move a over b,init_pos(a);pile_over(a, b)

            3.pile a onto b,init_pos(b);pile_over(a, b)

            4.pile a over b,pile_over(a, b)

            利用两个操作轻松解决。具体实现时设置一个place数组记录每个编号的方块对应的堆。

摘抄出处:http://blog.youkuaiyun.com/mobius_strip/article/details/12765319

再次,膜拜大神;(将模拟问题拆分为最基础的几个子问题,封装成为函数,减少代码量,同时思路更加清晰);

#include <iostream>
#include <stack>
#include <cstdio>

using namespace std;

stack<int> s[25];
int place[25];  //存放位置;
stack<int> s_t; //临时用来转换的堆;

void init_pos(int a){
    int p = place[a];
    while(!s[p].empty()){
        int v = s[p].top();
        if(v == a)
            break;
        s[v].push(v);
        place[v] = v;
        s[p].pop();
    }
}
void pile_over(int a, int b){
    int p_a = place[a];
    int p_b = place[b];
    while(!s[p_a].empty()){
        int v = s[p_a].top();
        if(v == a)
            break;
        s_t.push(v);
        s[p_a].pop();
    }
    s_t.push(a);
    s[p_a].pop();
    while(!s_t.empty()){
        int v = s_t.top();
        s[p_b].push(v);
        place[v] = p_b;
        s_t.pop();
    }
}
int main()
{
    int n;
    char oper[5], type[5];
    int a, b;
    while(cin >> n){
        for(int i = 0; i < n; ++i){
            s[i].push(i);
            place[i] = i;
        }
        while(scanf("%s", oper)){
            if(oper[0] == 'q')
                break;
            scanf("%d%s%d", &a, type, &b);
            if(place[a] == place[b]) //b在a之上,不处理;
                continue;
            if(oper[0] == 'm')  // 如果是move,将a之上的所有元素放回初始位置;
                init_pos(a);
            if(type[1] == 'n')  // 如果是onto,将b之上的所有元素放回初始位置;
                init_pos(b);
            pile_over(a, b);  
        }
        int s_k[25];
        for(int i = 0; i < n; ++i){
            cout << i << ':';
            int cnt = 0;
            while(!s[i].empty()){
                s_k[cnt++] = s[i].top();
                s[i].pop();
            }
            for(int j = cnt-1; j >= 0; --j){
                cout << ' ' << s_k[j];
            }
            cout << endl;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值