这道题不难,但是我做的时候把它当成了一道模拟题,针对四种移动方式,每种方式都写了一个函数,最后长达几百行代码。后来看看书上的解法,原来其实可以把移动方式拆分成更小的移动方式,每个移动方式都写成函数,移动的时候再组合起来,这样代码量就会减少很多。
1、原始解法,可以AC,但是方法很蠢
#include<cstdio>
#include<cstring>
#include<iostream>
#include<stack>
using namespace std;
struct block
{
int number;
};
struct a
{
stack <block> pile;
}arr[30];
int n;
int position[30];
void r1(int a,int b) //move a onto b:在將a搬到b上之前,先將a和b上的積木放回原來的位置
{
//放回原来的位置
int position_a,position_b,position_pre;
position_a = position[a];
position_b = position[b];
while(arr[position_a].pile.top().number != a)
{
position_pre = arr[position_a].pile.top().number;
position[arr[position_a].pile.top().number] = arr[position_a].pile.top().number;
arr[position_pre].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
}
while(arr[position_b].pile.top().number != b)
{
position_pre = arr[position_b].pile.top().number;
position[arr[position_b].pile.top().number] = arr[position_b].pile.top().number;
arr[position_pre].pile.push(arr[position_b].pile.top());
arr[position_b].pile.pop();
}
arr[position_b].pile.push(arr[position_a].pile.top());
position[a] = position_b;
arr[position_a].pile.pop();
}
void r2(int a,int b) //move a over b:在將a搬到b所在的那堆積木之上之前,先將a上的積木放回原來的位罝(b所在的那堆積木不動)
{
//放回原来的位置
int position_a,position_b,position_pre;
position_a = position[a];
position_b = position[b];
while(arr[position_a].pile.top().number != a)
{
position_pre = arr[position_a].pile.top().number;
position[arr[position_a].pile.top().number] = arr[position_a].pile.top().number;
arr[position_pre].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
}
arr[position_b].pile.push(arr[position_a].pile.top());
position[a] = position_b;
arr[position_a].pile.pop();
}
void r3(int a,int b) //pile a onto b:將a本身和其上的積木一起放到b上,在搬之前b上方的積木放回原位
{
int position_a,position_b,position_pre;
position_a = position[a];
position_b = position[b];
while(arr[position_b].pile.top().number != b)
{
position_pre = arr[position_b].pile.top().number;
position[arr[position_b].pile.top().number] = arr[position_b].pile.top().number;
arr[position_pre].pile.push(arr[position_b].pile.top());
arr[position_b].pile.pop();
}
//汉诺塔式,先放到其他arr,再搬回来
while(arr[position_a].pile.top().number != a)
{
position[arr[position_a].pile.top().number] = position_b;
arr[29].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
}
position[a] = position_b;
arr[29].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
while(!arr[29].pile.empty())
{
arr[position_b].pile.push(arr[29].pile.top());
arr[29].pile.pop();
}
}
void r4(int a,int b)
{
int position_a,position_b,position_pre;
position_a = position[a];
position_b = position[b];
//汉诺塔式,先放到其他arr,再搬回来
while(arr[position_a].pile.top().number != a)
{
position[arr[position_a].pile.top().number] = position_b;
arr[29].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
}
position[a] = position_b;
arr[29].pile.push(arr[position_a].pile.top());
arr[position_a].pile.pop();
while(!arr[29].pile.empty())
{
arr[position_b].pile.push(arr[29].pile.top());
arr[29].pile.pop();
}
}
int main()
{
int i,j,number1,number2,count;
char order1[10],order2[10],temp2[30];
scanf("%d",&n);
//初始化
for(i = 0;i < n;i++)
{
block temp;
temp.number = i;
position[i] = i;
arr[i].pile.push(temp);
}
while(1)
{
scanf("%s",order1);
if(order1[0] == 'q')
{
break;
}
scanf("%d",&number1);
scanf("%s",order2);
scanf("%d",&number2);
if(order1[0] == 'm')
{
if(order2[1] == 'n')
{
r1(number1,number2);
}
if(order2[1] == 'v')
{
r2(number1,number2);
}
}
if(order1[0] == 'p')
{
if(order2[1] == 'n')
{
r3(number1,number2);
}
if(order2[1] == 'v')
{
r4(number1,number2);
}
}
}
for(i = 0;i < n;i++)
{
count = 0;
printf("%d:",i);
while(!arr[i].pile.empty())
{
temp2[count++] = arr[i].pile.top().number;
arr[i].pile.pop();
}
for(j = count-1;j >=0;j--)
{
printf(" %d",temp2[j]);
}
printf("\n");
}
return 0;
}
2、书上例子,引用部分稍有修改,代码量剧减
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn]; //每个Pile[i]是一个vector
//找木块a所在的pile和height
void find_block(int a,int *p,int *h)
{
int t1,t2;
for(t1 = 0;t1 < n;t1++)
{
for(t2 = 0;t2 < pile[t1].size();t2++)
{
if(pile[t1][t2] == a)
{
*p = t1;
*h = t2;
return;
}
}
}
}
//把第p堆高度为h的木块上方的所有木块移回原位
void clear_above(int p,int h)
{
for(int i = h+1;i < pile[p].size();i++)
{
int b = pile[p][i];
pile[b].push_back(b);
}
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,i;
cin >> n;
string s1,s2;
for(i = 0;i < n;i++)
{
pile[i].push_back(i);
}
while(cin >> s1)
{
if(s1[0] == 'q')
{
break;
}
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;
}