2017 ACM-ICPC Beijing, D - Chinese Checkers
题意
给你一个魔改版的跳棋, 模拟操作, 最后输出局面
做法
用链表建完棋盘后就很简单了. 一开始写起来比较烦, 最后悟到建棋盘其实就是一个描述过程, 你大可用纯粹用代码来描述, 这不可避免大量的讨论; 也可以用数据来描述, 手动输入每个点六个方向的点是谁, 这枯燥的输入绝对无法正确搞定, 那么其实我应该要做的是trade off, 结合数据和代码来描述, 得到了一个比较好写的做法.
#include <bits/stdc++.h> using namespace std; struct Cell { int r, c; // r: region(1, 2, 3, 4, 5, 6, 0), c: color, occupid by who, Cell *L, *R, *UL, *UR, *LL, *LR; Cell() { r = c = 0; L = R = UL = UR = LL = LR = NULL; } } cells[20 * 20], *row[20], *loc = cells; Cell*goRight(Cell*x, int d) { for (int i = 0; i < d; ++i) x = x->R; return x; } int num[] = {0, 1, 2, 3, 4, 13, 12, 11, 10, 9, 10, 11, 12, 13, 4, 3, 2, 1}; int sp[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 5, 1, 1, 1}; int sc[] = {0, 0, 1, 1, 1, 5, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; void build() { Cell *p, *c; for (int i = 1; i <= 17; ++i) row[i] = loc++; for (int i = 1; i <= 17; ++i) { p = row[i]; for (int j = 1; j <= num[i]; ++j) { p->R = loc++; if (j != 1) p->R->L = p; p = p->R; } } for (int i = 2; i <= 17; ++i) { p = goRight(row[i - 1]->R, sp[i - 1]); c = i == 5 ? goRight(row[i]->R, 4) : row[i]->R; while (p && c) { c->UR = p; p->LL = c; p = p->R; c = c->R; } } for (int i = 2; i <= 17; ++i) { c = goRight(row[i]->R, sc[i]); p = i == 14 ? goRight(row[i - 1]->R, 4) : row[i - 1]->R; while (p && c) { c->UL = p; p->LR = c; p = p->R; c = c->R; } } } void recolor() { Cell*p; for (int i = 1; i <= 17; ++i) { p = row[i]->R; while (p) { p->c = 0; p = p->R; } } for (int i = 1; i <= 4; ++i) { p = row[i]->R; for (int j = 1; j <= i; ++j) { p->c = p->r = 1; p = p->R; } } for (int i = 5; i <= 8; ++i) { p = row[i]->R; for (int j = 4; i - 5 < j; --j) { p->c = p->r = 6; p = p->R; } p = goRight(row[i]->R, 9); for (int j = 4; i - 5 < j; --j) { p->c = p->r = 4; p = p->R; } } for (int i = 10; i <= 13; ++i) { p = row[i]->R; for (int j = 0; j < i - 9; ++j) { p->c = p->r = 3; p = p->R; } p = goRight(row[i]->R, 9); for (int j = 0; j < i - 9; ++j) { p->c = p->r = 5; p = p->R; } } for (int i = 14; i <= 17; ++i) { p = row[i]->R; for (int j = 4; i - 14 < j; --j) { p->c = p->r = 2; p = p->R; } } } Cell*go(Cell*c, string dir) { if (dir == "L") return c->L; if (dir == "R") return c->R; if (dir == "UL") return c->UL; if (dir == "UR") return c->UR; if (dir == "LL") return c->LL; return c->LR; } vector<pair<bool, Cell*> > path; int ok_col[7] = {0, 2, 1, 4, 3, 6, 5}; bool sym(int l, int r) { for (int i = l, j = r; i < j; ++i, --j) if (path[i].first != path[j].first) return false; if (r < l) return true; int cnt = 0; for (int i = l; i <= r; ++i) if (!path[i].first) ++cnt; return cnt > 0; } bool ok(int p, int c) { if (path[p].second->r == 0 || path[p].second->r == c || ok_col[path[p].second->r] == c) { return path[p].first; } return false; } vector<pair<int, int> > pos[7]; int go(Cell*c, string dir, int t) { if (!c) return t; return go(go(c, dir), dir, t + 1); } int main() { #ifdef lol freopen("d.in", "r", stdin); freopen("d.out", "w", stdout); #endif build(); int r, c, n; string dir; while (cin >> n) { recolor(); int player = 1; while (n--) { cin >> r >> c >> dir; //cout << r << ' ' << c << ' ' << dir << endl; Cell*p = row[r], *t; for (int i = 0; i < c; ++i) if (p) p = p->R; if (p && p->c == player) { path.clear(); t = p; while (t) { path.push_back(make_pair(t->c == 0, t)); t = go(t, dir); } // printf("%d\n", (int)path.size()); t = NULL; for (int i = 1; i < (int)path.size(); ++i) { if (sym(1, i - 1) && ok(i, p->c)) t = path[i].second; } if (t != NULL) { swap(t->c, p->c); // puts("ok"); } } for (int i = 1; i <= 6; ++i) { pos[i].clear(); } for (int i = 1; i <= 17; ++i) { p = row[i]->R; for (int j = 1; p; p = p->R, ++j) { if (p->c) pos[p->c].push_back(make_pair(i, j)); } } player %= 6; ++player; } for (int i = 1; i <= 6; ++i) { sort(pos[i].begin(), pos[i].end()); for (int j = 0; j < (int)pos[i].size(); ++j) printf("%d %d ", pos[i][j].first, pos[i][j].second); puts(""); } } return 0; }