现在的位置: 首页 > 综合 > 正文

POJ 1208 TheBlocks Problem (模拟+队列)

2018年04月23日 ⁄ 综合 ⁄ 共 1807字 ⁄ 字号 评论关闭

题意:NBlock,有四种操作可以相互移动Block使得他们叠起来。给出操作序列,求最后的状态。

Idea:模拟。

不算难,但是题意、一些细节要注意下。

 

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#define OP(s) cout<<#s<<"="<<s<<" ";
#define PP(s) cout<<#s<<"="<<s<<endl;
using namespace std;
static int s[300][300],h[300],pos[300];

void remove(int pa,int a)
{
    int i;
    for (i = 1; i <= h[pa]; i++)
        if (s[pa][i] == a) break;
    for (; i < h[pa]; i++)
        s[pa][i] = s[pa][i+1];
    h[pa]--;
}

void moveonto(int a,int pb,int b)
{
    int i;
    for (i = 1; i <= h[pb]; i++)
        if (s[pb][i] == b) break;
    for (int j = h[pb]; j > i; j--) //j >= i
        s[pb][j+1] = s[pb][j];
    s[pb][i+1] = a;//s[pb][i] = a;
    pos[a] = pb;
    h[pb]++;
}

void moveover(int a,int pb)
{
    s[pb][++h[pb]] = a;
    pos[a] = pb;
}

void pileonto(int pa,int a,int pb,int b)
{
    int i;
    for (i = 1; i <= h[pa]; i++)
        if (s[pa][i] == a) break;

    int j;
    for (j = 1; j <= h[pb]; j++)
        if (s[pb][j] == b) break;

    int sum = h[pa] - i + 1;
    for (int k = h[pb]; k > j; k--)
        s[pb][k+sum] = s[pb][k];
    for (int k = j+1; i <= h[pa]; i++,k++)
    {
        int t = s[pa][i];
        s[pb][k] = t;
        pos[t] = pb;
    }
    h[pa] -= sum;
    h[pb] += sum;
}

void pileover(int pa,int a,int pb,int b)
{
    int i;
    for (i = 1; i <= h[pa]; i++)
        if (s[pa][i] == a) break;

    int sum = h[pa] - i + 1;
    for (; i <= h[pa]; i++)
    {
        int t = s[pa][i];
        s[pb][++h[pb]] = t;
        pos[t] = pb;
    }
    h[pa] -= sum;
}

int main()
{
    freopen("test.txt","r",stdin);
    int N;
    scanf("%d",&N);
    for (int i = 0; i <= 30; i++)
    {
        s[i][1] = i;
        h[i] = 1;
        pos[i] = i;
    }
    string cmd;
    int a,b,pa,pb;
    while (cin>>cmd,cmd != "quit")
    {
        if (cmd == "move")
        {
            cin>>a>>cmd>>b;
            pa = pos[a];
            pb = pos[b];
            if (pa == pb) continue;

            if (cmd == "onto")
            {
                remove(pa,a);
                moveonto(a,pb,b);
            }
            else
            {
                remove(pa,a);
                moveover(a,pb);
            }
        }
        else
        {
            cin>>a>>cmd>>b;
            pa = pos[a];
            pb = pos[b];
            if (pa == pb) continue;

            if (cmd == "onto")
            {
                pileonto(pa,a,pb,b);
            }
            else
            {
                pileover(pa,a,pb,b);
            }
        }
    }
    for (int i = 0; i < N; i++)
    {
        printf("%d:",i);
        for (int j = 1; j <= h[i]; j++) printf(" %d",s[i][j]);
        printf("\n");
    }

    return 0;
}
/*
1/4
开始以为是道简单题,没多想就去写了。
1.开始题意给理解错了,把moveonto,A->B理解成了让a、b上其余的block都移动回最初的位置,题意其实是插入的意思;
2.a->b 开始写成了把a移动到第b堆,事实上b所在的堆 != 第b堆。
3.细节的把握,a-moveonto-b,a 是在b 的后面一个位置,而我写成了在b所在的位置

总之,对于稍复杂的模拟题做的不尽人意,加油~
*/

抱歉!评论已关闭.