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