UVa 101 木块问题

这道题不难,但是我做的时候把它当成了一道模拟题,针对四种移动方式,每种方式都写了一个函数,最后长达几百行代码。后来看看书上的解法,原来其实可以把移动方式拆分成更小的移动方式,每个移动方式都写成函数,移动的时候再组合起来,这样代码量就会减少很多。

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值