101 - The Blocks Problem
终于!!!自己辛辛苦苦想了一天,没有外力的借助下第一次解决了一道模拟题。做完这个题,还是有点总结,总之,一定要把代码写的模块化,让代码看起来有优美的感觉。是“某种动作”最好封装为一个函数。让代码更加简洁。
唔~下面见题解。
[此处是原题](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=37)
题目大意就是说。我是这样理解着去做题的。我把起初定为n个位置,每个位置上有一个该位置对应的木块,比如说1号位置起初就有一个1号木块。定义了以下四种动作。
move a onto b:把a和b上方的木块全部归位,然后把a摞在b上面。
move a over b:把a上方的木块全部归位,然后把a放在b所在木块堆的顶部。
pile a onto b:把b上方的木块全部归位,然后把a及上面的木块整体摞在b上面
pile a over b:把a及上面的木块整体摞在b所在木块堆的顶部。
---------*此处操作中有无效操作,这句很重要,如果要操作的俩个木块在一个位置上,我们就把他视为无效操作,另外归为原位,即放到原来对应的位置,如1号木块对应一号位置*。
**具体细节见代码注释**
另外:最下方有额外的测试数据。
#include <iostream>
#include <cstring>
#include <deque> //这里我用了一个双向队列打算模拟每个位置n;
using namespace std;
int block_P[25]; //这个数组的意思是说把每个木块对应的位置保存起来,如block_p[1]保存的是一号木块的位置
void out(int n);
void mo(int a, int b); //这是我定义的四个命令
void mr(int a, int b);
void po(int a, int b);
void pr(int a, int b);
void cle(int b); //这个函数的意思就是说检查b号木块上方有没有其他木块,有就移回原位
void adda_to_b(int a, int b); //此函数为移动函数,将a移动到b号上方
int num(char *a, char *b); //判断是哪个命令
int judge(int a, int b); //判断是否是无效命令
deque<int> block[25]; //这个队列最好设置为全局变量,不然下面处理很麻烦
int main()
{
int n;
cin >> n;
int o = 0;
int i, j;
for (i = 0; i < n; i++)
{
block[i].push_back(i); //初始化编号
block_P[i] = i;
}
int first_, end_;
char first[5], end[5];
while (cin >> first)
{
if(first[0]=='q')
break;
cin>> first_ >> end >> end_;
int judge = num(first, end);
if (judge == 1)
mo(first_, end_);
if (judge == 2)
mr(first_, end_);
if (judge == 3)
po(first_, end_);
if (judge == 4)
pr(first_, end_);
o++;
}
out(n);
}
int num(char *a, char *b)
{
if (a[0] == 'm' && b[3] == 'o')
return 1;
if (a[0] == 'm' && b[3] == 'r')
return 2;
if (a[0] == 'p' && b[3] == 'o')
return 3;
if (a[0] == 'p' && b[3] == 'r')
return 4;
}
void cle(int b)
{
int bp = block_P[b];//b号木块的位置
while (block[bp].back() != b) //首先判断b号木块所在位置的最上方是不是b,如果不是进行归位
{
block[block[bp].back()].push_back(block[bp].back());
block_P[block[bp].back()] = block[bp].back();
block[bp].pop_back();
}
}
void adda_to_b(int a, int b)
{
int bp = block_P[b];
int ap = block_P[a];
int o = 0;
int uu[25];
while (block[ap].back() != a)//此处操作是比如进行over操作时,我们需要将木块连同上方所有木块移动
{ //这里用数组先保存,最后再按序插入。否则最后的答案可能会顺序颠倒。
uu[o++] = block[ap].back();
block_P[block[ap].back()] = bp;
block[ap].pop_back();
}
block[bp].push_back(a);
block[ap].pop_back();
block_P[a] = bp;
if(o!=0){
for (int i =o-1; i >=0;i--){
block[bp].push_back(uu[i]);
}
}
}
int judge(int a,int b){
int bp = block_P[b];
int ap = block_P[a];
if (bp == ap)
return 1;
return 0;
}
void mo(int a, int b)
{
if(judge(a,b)==0)
{
cle(b);
cle(a);
adda_to_b(a, b);
}}
void mr(int a, int b)
{
if (judge(a, b)==0)
{
cle(a);
adda_to_b(a, b);
}}
void po(int a, int b)
{
if (judge(a, b)==0)
{
cle(b);
adda_to_b(a, b);
}}
void pr(int a, int b)
{
if (judge(a, b)==0){
adda_to_b(a, b);
}}
void out(int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%d:", i);
while (!block[i].empty())
{
printf(" %d", block[i].front());//注意输出格式
block[i].pop_front();
}
printf("\n");
}
}
}
9
move 4 onto 1
move 8 onto 3
move 7 onto 8
move 8 onto 1
move 2 onto 6
move 1 over 6
move 3 onto 7
move 8 onto 3
pile 2 onto 3
move 4 onto 5
move 6 onto 4
pile 3 onto 4
quit
0: 0
1:
2;
3:
4:
5: 5 4 3 2 1
6: 6
7: 7
8: 8
4
pile 0 over 1
pile 2 over 3
move 1 onto 3
quit
0: 0
1:
2: 2
3: 3 1
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
pie 4 over 3
pie 1 over 2
pie 0 onto 1
pie 4 over 5
pie 5 onto 9
quit
0:
1: 1 0
2: 2
3: 3
4:
5:
6:
7:
8:
9: 9 5 8 7 6 4