SPOJ TETRIS2D - Exciting Time

数据结构homework出这种题简直丧心病狂好吧。。

注意题意没说请的下落其实就是消去一行的上面所有点高度统一减小1,于是会有悬空的情况出现——怕是假的俄罗斯方块= =

做法就是每列维护一个链表,里面的节点表示一个方块,同一行的方块同时连向一个表示行高的头节点。

插入一个新方块就在每个链表的尾部操作一番,利用相对位置就可以在行链表里面爬;一行满了就消去一行,在每个链表中删即可。

#include <climits>
#include <assert.h>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;

char gchar() {
    char r = getchar();
    while (r == ' ' || r == '\n' || r == '\r')
        r = getchar();
    return r;
}

int id(char t) {
    switch (t) {
        case 'I':
            return 0;
        case 'J':
            return 1;
        case 'L':
            return 2;
        case 'O':
            return 3;
        case 'S':
            return 4;
        case 'T':
            return 5;
        case 'Z':
            return 6;
    }
    while (1);
    assert(false);
    return -1;
}
int getScore(int t) {
    switch (t) {
        case 1:
            return 100;
        case 2:
            return 250;
        case 3:
            return 400;
        case 4:
            return 1000;
    }
    while (1);
    assert(false);
    return -1;
}

int tile[][4][4][2] = {
    {
        {
            {0, 0}, {0, 1}, {0, 2}, {0, 3}
        },
        {
            {0, 0}, {1, 0}, {2, 0}, {3, 0}
        },
        {
            {0, 0}, {0, 1}, {0, 2}, {0, 3}
        },
        {
            {0, 0}, {1, 0}, {2, 0}, {3, 0}
        }
    },
    {
        {
            {0, 0}, {0, 1}, {0, 2}, {1, 0}
        },
        {
            {0, 0}, {1, 0}, {2, 0}, {2, 1}
        },
        {
            {-1, 2}, {0, 0}, {0, 1}, {0, 2}
        },
        {
            {0, 0}, {0, 1}, {1, 1}, {2, 1}
        }
    },
    {
        {
            {0, 0}, {0, 1}, {0, 2}, {1, 2}
        },
        {
            {0, 0}, {0, 1}, {1, 0}, {2, 0}
        },
        {
            {0, 0}, {1, 0}, {1, 1}, {1, 2}
        },
        {
            {0, 0}, {-2, 1}, {-1, 1}, {0, 1}
        }
    },
    {
        {
            {0, 0}, {0, 1}, {1, 0}, {1, 1}
        },
        {
            {0, 0}, {0, 1}, {1, 0}, {1, 1}
        },
        {
            {0, 0}, {0, 1}, {1, 0}, {1, 1}
        },
        {
            {0, 0}, {0, 1}, {1, 0}, {1, 1}
        }
    },
    {
        {
            {0, 0}, {0, 1}, {1, 1}, {1, 2}
        },
        {
            {0, 0}, {1, 0}, {-1, 1}, {0, 1}
        },
        {
            {0, 0}, {0, 1}, {1, 1}, {1, 2}
        },
        {
            {0, 0}, {1, 0}, {-1, 1}, {0, 1}
        }
    },
    {
        {
            {0, 0}, {0, 1}, {0, 2}, {1, 1}
        },
        {
            {0, 0}, {1, 0}, {2, 0}, {1, 1}
        },
        {
            {0, 0}, {-1, 1}, {0, 1}, {0, 2}
        },
        {
            {0, 0}, {-1, 1}, {0, 1}, {1, 1}
        }
    },
    {
        {
            {0, 0}, {-1, 1}, {0, 1}, {-1, 2}
        },
        {
            {0, 0}, {1, 0}, {1, 1}, {2, 1}
        },
        {
            {0, 0}, {-1, 1}, {0, 1}, {-1, 2}
        },
        {
            {0, 0}, {1, 0}, {1, 1}, {2, 1}
        },
    },
};

const int N = 3e5 + 100;
int w, n;
struct Node;
struct Row:vector<Node*> {
    int h;
    Row *up, *dw;
    Row* go(int);
} hd[N * 4], EXT_BOT;
Row* Row::go(int d) {
    Row*r = this;
    if (d < 0) {
        while (d < 0) {
            r = r->dw;
            if (r == NULL) return &EXT_BOT;
            ++d;
        }
    } else {
        while (0 < d) {
            r = r->up;
            --d;
        }
    }
    return r;
}
struct Node {
    Node *dw, *up;
    Row *row;
    int col;
} node_pool[N * 4], *loc, *top[N], *bot[N];
Node* newNode(Row *row, int col) {
    loc->row = row;
    loc->col = col;
    loc->dw = loc->up = NULL;
    return loc++;
}

Row* getPos(int t, int col, int ang) {
    int (*d)[2] = tile[t][ang];
    Row* r;
    int max_h = INT_MIN;
    for (int i = 0; i < 4; ++i) {
        int tcol = col + d[i][1];
        Row *tr = top[tcol]->row->go(-d[i][0]);
        if (tr->h > max_h) {
            max_h = tr->h;
            r = tr;
        }
    }
    return r->up;
}


int main() {
#ifdef lol
    freopen("TETRIS2D.in", "r", stdin);
    freopen("TETRIS2D.out", "w", stdout);
#endif
    EXT_BOT.h = INT_MIN;

    /*
       char brd[10][10 * 4];
       for (int i = 0; i < 7; ++i) {
       printf("On tile %d:\n", i);
       memset(brd, ' ', sizeof brd);
       for (int j = 0; j < 4; ++j) {
       int row = 5, col = j * 10;
       for (int k = 0; k < 4; ++k)
       brd[row + tile[i][j][k][0]]
       [col + tile[i][j][k][1]] = '*';
       }
       for (int i = 0; i < 10; ++i, puts(""))
       for (int j = 0; j < 10 * 4; ++j)
       putchar(brd[10 - i - 1][j]);
       puts("");
       }
       return 0;
       */

    int T; scanf("%d", &T);
    for (int cas = 1; cas <= T; ++cas) {
        printf("Case #%d:\n", cas);
        scanf("%d%d", &w, &n);
        loc = node_pool;
        hd[0].dw = NULL;
        hd[0].up = &hd[1];
        hd[0].h = 0;
        hd[0].clear();
        for (int i = 1; i <= n * 4; ++i) {
            hd[i].dw = &hd[i - 1];
            hd[i].up = &hd[i + 1];
            hd[i].h = i;
            hd[i].clear();
        }
        hd[n * 4 + 1].dw = &hd[n * 4];
        for (int i = 0; i < w; ++i)
            bot[i] = top[i] = newNode(&hd[0], i);

        int scr = 0;
        vector<Row*> full;
        while (n--) {
            int t = id(gchar()), col, ang;
            scanf("%d%d", &col, &ang);
            ang /= 90;
            Row* pos = getPos(t, col, ang);
            //printf("Pos : %d\n", pos->h);
            full.clear();
            for (int i = 0; i < 4; ++i) {
                Row*tmp = pos->go(tile[t][ang][i][0]);
                Node*tnd = newNode(tmp, col + tile[t][ang][i][1]);
                tmp->push_back(tnd);
                if ((int)tmp->size() == w)
                    full.push_back(tmp);
                int tcol = col + tile[t][ang][i][1];
                top[tcol]->up = tnd;
                tnd->dw = top[tcol];
                top[tcol] = tnd;
            }
            if (full.size() != 0) {
                scr += getScore(full.size());
                for (auto&&r : full) {
                    for (auto&&i : *r) {
                        i->dw->up = i->up;
                        if (i->up) i->up->dw = i->dw;
                        if (top[i->col] == i)
                            top[i->col] = i->dw;
                    }
                    r->dw->up = r->up;
                    r->up->dw = r->dw;
                }
            }
            /*
            for (Row* t = hd[0].up; t != NULL; t->h = t->dw->h + 1, t = t->up);
            printf("%d", top[0]->row->h);
            for (int i = 1; i < w; ++i) {
                printf(" %d", top[i]->row->h);
            }
            puts("");
            */
        }
        printf("%d\n", scr);
        for (Row* t = hd[0].up; t != NULL; t->h = t->dw->h + 1, t = t->up);
        printf("%d", top[0]->row->h);
        for (int i = 1; i < w; ++i) {
            printf(" %d", top[i]->row->h);
        }
        puts("");
    }
    return 0;
}

 

posted @ 2017-09-30 17:58  ichneumon  阅读(444)  评论(0编辑  收藏  举报