uva-101 && poj 1208 The Blocks Problem (模拟栈)

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18191

题意:   下面的步骤看别人的,

機器手臂有以下幾種合法搬積木的方式(a和b是積木的編號):
move a onto b
在將a搬到b上之前,先將a和b上的積木放回原來的位置(例如:1就放回1的最開始位罝)
move a over b
在將a搬到b所在的那堆積木之上之前,先將a上的積木放回原來的位罝(b所在的那堆積木不動)
pile a onto b
將a本身和其上的積木一起放到b上,在搬之前b上方的積木放回原位
pile a over b
將a本身和其上的積木一起搬到到b所在的那堆積木之上
quit
動作結束

前四個動作中若a=b,或者a, b在同一堆積木中,那麼這樣的動作算是不合法的。所有不合法的動作應該被忽略,也就是對各積木均無改變

 

思路:就是一个模拟栈的问题,对自己还是有一点难度,折腾了几天,最后在poj找到测试数据,才摆脱re的折磨。基础差,各种差!!!
pile[i][i]表示第i堆第i个数,in[i]表示第i堆的总数,q[i]表示第i张牌的当前位置,模拟就好了,注意细节。

奉上一组poj上的测试数据:

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

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define ll long long
#define inf 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)

#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("a.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);
#define N 100005
using namespace std;

const int len = 100;

int pile[len][len],in[len],q[len]; //pile[i][i]表示第i堆牌第i张,in表示第i堆牌总数,q表示第i张牌的当前位置

int pd(int x,int y) //判断x跟y在不在同一堆
{
    if(q[x]==q[y]) return 1;  //判断当前位置  是不是在同一堆即可
    return 0;
}

void solve(int x) //将 x上的积木放回原来的位置 不包括x
{
    int i,ans,y,z;   //从x这一堆  从上往下找
    ans=in[q[x]]; //当前堆 积木总数
    y=q[x]; //当前堆编号
    for(i=ans;pile[y][i]!=x;i--)
    {
        z=pile[y][i]; //当前堆需要移动的积木编号
        q[z]=z; //当前积木移到初始位置,那么 当前积木移动后当前位置变为自身编号
        pile[z][++in[z]]=z; //重新存储
        in[y]--;  //当前堆减1
    }
}

void solve2(int x,int y) //将 x本身和其上的积木一起放到y上,并且按顺序放
{
    int i,ans=0,z,y1,y2;
    for(i=in[q[x]];pile[q[x]][i]!=x;i--)
    {
        ans++;  //求出x在当前堆的位置
    }
    z=in[q[x]];  //当前堆 总数
    y1=q[x];//当前堆 编号
   
    for(i=z-ans;i<=z;i++)  //移动
    {
        q[pile[y1][i]]=q[y]; //把积木的当前位置改掉
        pile[q[y]][++in[q[y]]]=pile[y1][i]; //移动
        in[y1]--; //总数减 1
    }
}

int main()
{
    //Read();  //文件读取
    int n,i,j;
    char s[30],a[10],b[10];
    int c,d;
    while(scanf("%d",&n)!=EOF)  //读入n,代表有n张牌
    {
        getchar();
        CL(pile,0); //清空数组
        CL(q,0);
        CL(in,0);
        for(i=0;i<n;i++) //初始化
        {
            in[i]=1;
            q[i]=i;
            pile[i][1]=i;
        }
        while(1)
        {
            gets(s);
            if(s[0]=='q') break;
            sscanf(s,"%s %d %s %d",a,&c,b,&d);
            if(c==d||pd(c,d))   continue;
            if(strcmp(a,"move")==0)
            {
                if(strcmp(b,"onto")==0)
                {
                    if(in[q[c]]>1)solve(c);
                    if(in[q[d]]>1)solve(d);
                    pile[q[d]][++in[q[d]]]=pile[q[c]][in[q[c]]--];
                    q[c]=q[d];
                }
                else if(strcmp(b,"over")==0)
                {
                    if(in[q[c]]>1) solve(c);
                    pile[q[d]][++in[q[d]]]=pile[q[c]][in[q[c]]--];
                    q[c]=q[d];
                }
            }
            else if(strcmp(a,"pile")==0)
            {
                if(strcmp(b,"onto")==0)
                {
                    if(in[q[d]]>1)solve(d);
                    solve2(c,d);
                }
                else if(strcmp(b,"over")==0)
                {
                    solve2(c,d);
                }
            }
        }
        for(i=0;i<n;i++)
        {
            if(in[i]==0)
            {
                printf("%d:\n",i);
            }
            else
            {
                printf("%d:",i);
                for(j=1;j<=in[i];j++)
                {
                    if(j!=in[i]) printf(" %d",pile[i][j]);
                    else printf(" %d\n",pile[i][j]);
                }
            }
        }
    }
    return 0;
}


下面是别人用vector写的,比我的规范多了! 

#include <cstdio>
#include <vector>
#include <stack>
using namespace std;


const int MAXN = 30;

vector<int> pile[MAXN];
int pos[MAXN];

const int MOVE = 0;
const int PILE = 1;
const int ONTO = 0;
const int OVER = 1;

void init(int n){
    for(int i=0; i<n; i++){
        pile[i].clear();
        pile[i].push_back(i);
        pos[i] = i;
    }
}

bool ReadInstruct(int &insA, int &insB, int &x, int &y)
{
    char s1[10];
    scanf("%s", s1);
    if(s1[0] == 'q') return false;

    if(s1[0] == 'm') insA = MOVE;
    else insA = PILE;
    scanf("%d", &x);
    scanf("%s", s1);
    if(s1[1] == 'n') insB = ONTO;
    else insB = OVER;
    scanf("%d", &y);
    return true;
}

void PrintPile(int n)
{
    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");
    }
}


void ReturnAbove(int x){
    int px = pos[x];
    while(1){
        int y = pile[px].back();
        if(y == x) break;
        pile[px].pop_back();
        pile[y].push_back(y);
        pos[y] = y;
    }
}

void StoreAbove(stack<int> &stk, int x){
    int px = pos[x];
    while(1){
        int y = pile[px].back();
        pile[px].pop_back();
        stk.push(y);
        if(y == x) break;
    }
}

void MoveTo(stack<int>& stk, int y) //move stk to y
{
    int py = pos[y];
    while(!stk.empty()){
        int x = stk.top(); stk.pop();
        pos[x] = py;
        pile[py].push_back(x);
    }
}


int main(){
    //freopen("in", "r", stdin);
    int n;
    scanf("%d", &n);
    init(n);
    int insA, insB, a, b;
    while(1){
        if(ReadInstruct(insA, insB, a, b) == false)
            break;
        if(pos[a] == pos[b]) continue;
        if(insA == MOVE) //move
            ReturnAbove(a);
        if(insB == ONTO) //onto
            ReturnAbove(b);
        stack<int> stk;
        StoreAbove(stk, a);
        MoveTo(stk, b);
    }
    PrintPile(n);
}


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值