Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Fuck my life
- #include <bits/stdc++.h>
- using namespace std;
- typedef pair<int, int> pii;
- const int MAXN = 2005;
- const int oo = (int)1e9 + 7;
- // Board is rotated for easier imagination
- struct Piece {
- char type;
- int r, c;
- };
- struct Strip {
- int r1, r2, c;
- };
- struct Rect {
- int height;
- bool forbid, isStart, isFinish;
- };
- bool inBoard(int c) {return c >= 1 && c <= 8;}
- vector<Strip> getStrips(vector<Piece> pieces) {
- vector<set<int>> blocks(9);
- for(int c = 1; c <= 8; ++c) {
- blocks[c].insert(-20);
- blocks[c].insert(1e8 + 20);
- }
- for(Piece p: pieces) {
- blocks[p.c].insert(p.r);
- }
- auto cellBlocked = [&](int r, int c) {
- return blocks[c].count(r);
- };
- vector<Strip> res;
- auto addCell = [&](int r, int c) {
- // printf("addCell %d %d\n", r, c);
- res.push_back({r, r, c});
- };
- auto addStripKnight = [&](int r, int c) {
- int DX[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
- int DY[8] = {1, 2, 2, 1, -1, -2, -2, -1};
- for(int dir = 0; dir < 8; ++dir) {
- int curR = r + DX[dir], curC = c + DY[dir];
- if (inBoard(curC) && !cellBlocked(curR, curC))
- addCell(curR, curC);
- }
- };
- auto addStripKing = [&](int r, int c) {
- for(int curR = r-1; curR <= r+1; ++curR) {
- for(int curC = c-1; curC <= c+1; ++curC) {
- // printf("curR, curC: %d %d\n", curR, curC);
- if (!(curR == r && curC == c) && inBoard(curC) && !cellBlocked(curR, curC)) addCell(curR, curC);
- }
- }
- };
- auto addStripBishop = [&](int r, int c) {
- int DX[4] = {-1, 1, 1, -1};
- int DY[4] = {-1, -1, 1, 1};
- for(int dir = 0; dir < 4; ++dir) {
- int curR = r, curC = c;
- while (true) {
- curR += DX[dir]; curC += DY[dir];
- if (!inBoard(curC) || cellBlocked(curR, curC)) break;
- addCell(curR, curC);
- }
- }
- };
- auto addStripRook = [&](int r, int c) {
- for(int deltaC = -1; deltaC <= 1; deltaC += 2) {
- int curR = r, curC = c;
- while (true) {
- curC += deltaC;
- if (!inBoard(curC) || cellBlocked(curR, curC)) break;
- addCell(curR, curC);
- }
- }
- int rDown = *blocks[c].upper_bound(r);
- int rUp = *prev(blocks[c].lower_bound(r));
- res.push_back({rUp, rDown, c});
- };
- auto addStripQueen = [&](int r, int c) {
- addStripBishop(r, c);
- addStripRook(r, c);
- };
- for(Piece p: pieces) {
- addCell(p.r, p.c);
- if (p.type == 'K') addStripKing(p.r, p.c);
- else if (p.type == 'Q') addStripQueen(p.r, p.c);
- else if (p.type == 'R') addStripRook(p.r, p.c);
- else if (p.type == 'B') addStripBishop(p.r, p.c);
- else if (p.type == 'N') addStripKnight(p.r, p.c);
- }
- return res;
- }
- vector<vector<Rect>> getBoard(vector<Strip> strips, int xs, int ys, int xt, int yt) {
- set<int> _poi;
- _poi.insert(-20);
- _poi.insert(1e8+20);
- auto addToPoi = [&](int x) {
- if (x >= -20 && x <= 1e8+20)
- _poi.insert(x);
- };
- for(int delta = -2; delta <= 2; ++delta) {
- for(Strip s: strips) {
- addToPoi(s.r1 + delta);
- addToPoi(s.r2 + delta);
- }
- addToPoi(xs + delta);
- addToPoi(xt + delta);
- }
- vector<int> poi(_poi.begin(), _poi.end());
- // for(int x: poi) printf("%d ", x);
- // puts("");
- vector<vector<int>> addStrip(9, vector<int>());
- vector<vector<int>> removeStrip(9, vector<int>());
- for(Strip s: strips) {
- addStrip[s.c].push_back(s.r1);
- removeStrip[s.c].push_back(s.r2+1);
- }
- for(int c = 1; c <= 8; ++c) {
- sort(addStrip[c].begin(), addStrip[c].end());
- sort(removeStrip[c].begin(), removeStrip[c].end());
- }
- vector<vector<Rect>> res(poi.size()-1, vector<Rect>(9));
- for(int c = 1; c <= 8; ++c) {
- int iAdd = 0, iRemove = 0, cnt = 0;
- for(int i = 0; i < poi.size()-1; ++i) {
- while (iAdd < addStrip[c].size() && addStrip[c][iAdd] <= poi[i]) {
- ++cnt;
- ++iAdd;
- }
- while (iRemove < removeStrip[c].size() && removeStrip[c][iRemove] <= poi[i]) {
- --cnt;
- ++iRemove;
- }
- res[i][c] = {poi[i+1]-poi[i], cnt > 0, poi[i] == xs && c == ys, poi[i] == xt && c == yt};
- }
- }
- return res;
- }
- int getDistFromStartToFinish(vector<vector<Rect>> board) {
- pii start, finish;
- int n = board.size();
- for(int i = 0; i < n; ++i) {
- for(int j = 1; j <= 8; ++j) {
- if (board[i][j].isStart) start = {i, j};
- if (board[i][j].isFinish) finish = {i, j};
- }
- }
- vector<vector<int>> dist(n, vector<int>(9, oo));
- vector<vector<bool>> avail(n, vector<bool>(9, true));
- priority_queue<pair<int, pii>> q;
- dist[start.first][start.second] = 0;
- q.push({0, start});
- while (!q.empty()) {
- pii cur = q.top().second; q.pop();
- int x = cur.first, y = cur.second;
- if (board[x][y].isFinish) return dist[x][y];
- if (!avail[x][y]) continue;
- avail[x][y] = false;
- for(int dx = -1; dx <= 1; ++dx) {
- for(int dy = -1; dy <= 1; ++dy) {
- int u = x + dx, v = y + dy;
- int w = (dx != 0) ? board[x][y].height : 1;
- if (u >= 0 && u < n && v >= 1 && v <= 8 && avail[u][v] && !board[u][v].forbid && dist[u][v] > dist[x][y] + w) {
- dist[u][v] = dist[x][y] + w;
- q.push({-dist[u][v], {u, v}});
- }
- }
- }
- }
- return -1;
- }
- int main() {
- freopen("input.txt", "r", stdin);
- int xs, ys;
- scanf("%d%d", &xs, &ys);
- int xt, yt;
- scanf("%d%d", &xt, &yt);
- int n;
- cin >> n;
- vector<Piece> pieces;
- for(int i = 0; i < n; ++i) {
- string type; int x, y;
- cin >> type >> x >> y;
- pieces.push_back({type[0], x, y});
- }
- vector<Strip> strips = getStrips(pieces);
- // for(Strip s: strips) {
- // printf("r1, r2, c: %d %d %d\n", s.r1, s.r2, s.c);
- // }
- vector<vector<Rect>> board = getBoard(strips, xs, ys, xt, yt);
- // for(int i = 0; i < board.size(); ++i) {
- // for(int j = 1; j <= 8; ++j) {
- // printf("%d ", board[i][j].forbid ? 0 : 1);
- // }
- // puts("");
- // }
- // for(int i = 0; i < board.size(); ++i) {
- // for(int j = 1; j <= 8; ++j) {
- // printf("(%d, %d) ", board[i][j].height, board[i][j].forbid ? 0 : 1);
- // }
- // puts("");
- // }
- int ans = getDistFromStartToFinish(board);
- printf("%d\n", ans);
- return 0;
- }
Add Comment
Please, Sign In to add comment