(STL,vector)木块问题

题目:

输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置。现对这些木块进行操作,操作分为四种。

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所在的木块的堆的上面。

当输入quit时,结束操作并输出0~n-1的位置上的木块情况

Sample Input
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
Sample Output
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:

分析与解答:

1.提取指令之间的共同点,编写函数以减少代码量
经观察:
pile a onto b和move a onto b,在移动之前,都需要把b上方木块归位。
move a onto b和move a over b,在移动之前,都需要把a上方木块归位。
两个都是一个意思,把第p堆高度位h的木块上方的所有木块移回原位
四条指令在做完预备工作(归位)之后,都是把a这个堆高度位h及上方的木块整体移到b这个堆整体的顶部

有人要问为什么需要有h
如果
2:2 3 4 5
6:6 7 8 9

pile 3 over 6

2:2
6:6 7 8 9 3 4 5
懂了吧,并不是只有从最底部开始移动
2.利用vector
vector< int>pile[maxn]像是一个二维数组,只不过一维大小固定二位不固定
vector< int>a
a.size()读取大小
a.resize(b)改变大小(只保留前b个数,下标0到b-1的元素)
a.push_back(b)向尾部添加元素b
a.pop_back()删除最后一个元素
本题每个木块堆的高度不确定,而木块堆的个数确定有n个,因此用vector合适

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn];

//找到木块a所在的pile和height,以引用的形式返回调用者

void find_block(int a,int&p,int &h){//p和h是需要通过这个函数求的,由于是引用,所以return后p,h的值就求出来了 
    for(p=0;p<n;++p){
        for(h=0;h<pile[p].size();h++){
            if(pile[p][h]==a) return ;
        }
    }
}
//把第p堆高度为h的木块上方的所有木块移回原位

void clear_above(int p,int h){
    for(int i=h+1;i<pile[p].size();++i){
        int m=pile[p][i];
        pile[m].push_back(m);
    }
    pile[p].resize(h+1);
} 
//把第p堆高度为h及其上方的木块整体移动到p2堆的顶部

void pile_onto(int p,int h,int p2){
    for(int i=h;i<pile[p].size();i++)
        pile[p2].push_back(pile[p][i]);
    pile[p].resize(h);
}
void print()
{
    for (int i = 0; i < n; i++)
    {
        printf("%d:", i);
        for (int j = 0; j < pile[i].size(); j++)
            printf(" %d", pile[i][j]);
        printf("\n");

    }
}


int main()
{
    int a, b;
    cin >> n;
    string s1, s2;
    for (int i = 0; i < n; i++)pile[i].push_back(i);
    while (cin >> s1 ,s1!="quit")
    {   
        cin>> a >> s2 >> b;
        int pa, pb, ha, hb;
        find_block(a, pa, ha);
        find_block(b, pb, hb);
        if (pa == pb) continue;//非法指令
        if (s2 == "onto") clear_above(pb, hb);
        if (s1 == "move") clear_above(pa, ha);
        pile_onto(pa, ha, pb);

    }
    print();

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40828914/article/details/81112296
今日推荐