Advertisement
erek1e

CEOI '20 - Chess Rush (36pts)

Jul 7th, 2023
803
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.46 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. const int INF = 1e8;
  6. const int BASE = 1e9 + 7;
  7. int add(int x, int y) {
  8.     x += y;
  9.     if (x >= BASE) return x-BASE;
  10.     return x;
  11. }
  12.  
  13. int R, C;
  14. bool sameDiagonal(int x1, int y1, int x2, int y2) {
  15.     return x1-y1 == x2-y2 || x1+y1 == x2+y2;
  16. }
  17. bool sameColor(int x1, int y1, int x2, int y2) {
  18.     return ((x1+y1)-(x2+y2)) % 2 == 0;
  19. }
  20. bool inBoard(int r, int c) {
  21.     return r >= 1 && c >= 1 && r <= R && c <= C;
  22. }
  23. pair<int, int> diagonalIntersect(int x1, int y1, int x2, int y2) {
  24.     // x + y = x1 + y1
  25.     // x - y = x2 - y2
  26.     // x = (x1 + y1 + x2 - y2) / 2
  27.     // y = (x1 + y1 - x2 + y2) / 2
  28.     return {(x1+y1+x2-y2)/2, (x1+y1-x2+y2)/2};
  29. }
  30.  
  31. pair<int, int> downRight(int r, int c) {
  32.     return {r+C-c, C};
  33. }
  34. pair<int, int> downLeft(int r, int c) {
  35.     return {r+c-1, 1};
  36. }
  37.  
  38. pair<int, int> combine(pair<int, int> a, pair<int, int> b) { // (moves, ways)
  39.     if (a.first == b.first) return {a.first, add(a.second, b.second)};
  40.     else if (a.first < b.first) return a;
  41.     else return b;
  42. }
  43.  
  44. // going right
  45. pair<int, int> solveBishop(int c1, int cr) {
  46.     vector<int> ways(2*C), moves(2*C, INF);
  47.     ways[c1-1] = 1, moves[c1-1] = 1;
  48.     for (int r = 2; r <= R; ++r) {
  49.         vector<int> ways2(2*C), moves2(2*C, INF);
  50.  
  51.         auto can = [&](int pos, int dir, int w, int m) {
  52.             if (0 <= pos && pos < C) {
  53.                 if (m < moves2[dir*C+pos]) moves2[dir*C+pos] = m, ways2[dir*C+pos] = w;
  54.                 else if (m == moves2[dir*C+pos]) ways2[dir*C+pos] = add(ways2[dir*C+pos], w);
  55.             }
  56.         };
  57.         for (int i = 0; i < 2*C; ++i) {
  58.             int c = i%C, dir = i/C;
  59.             if (dir == 0) { // going right
  60.                 can(c+1, 0, ways[i], moves[i]);
  61.                 can(c-1, 1, ways[i], moves[i]+1);
  62.             } else { // going left
  63.                 can(c+1, 0, ways[i], moves[i]+1);
  64.                 can(c-1, 1, ways[i], moves[i]);
  65.             }
  66.         }
  67.         ways = ways2, moves = moves2;
  68.     }
  69.     return combine({moves[cr-1], ways[cr-1]}, {moves[cr-1+C], ways[cr-1+C]});
  70. }
  71.  
  72. pair<int, int> solveKing(int c1, int cr) {
  73.     vector<int> ways(C), moves(C, INF);
  74.     ways[c1-1] = 1, moves[c1-1] = 0;
  75.     for (int r = 2; r <= R; ++r) {
  76.         vector<int> ways2(C), moves2(C, INF);
  77.  
  78.         auto can = [&](int pos, int w, int m) {
  79.             if (0 <= pos && pos < C) {
  80.                 if (m < moves2[pos]) moves2[pos] = m, ways2[pos] = w;
  81.                 else if (m == moves2[pos]) ways2[pos] = add(ways2[pos], w);
  82.             }
  83.         };
  84.         for (int c = 0; c < C; ++c) {
  85.             can(c+1, ways[c], moves[c]+1);
  86.             can(c-1, ways[c], moves[c]+1);
  87.             can(c  , ways[c], moves[c]+1);
  88.         }
  89.         ways = ways2, moves = moves2;
  90.     }
  91.     return {moves[cr-1], ways[cr-1]};
  92. }
  93.  
  94. int main() {
  95.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  96.     int Q; cin >> R >> C >> Q;
  97.     while (Q--) {
  98.         char t; int c1, cr;
  99.         cin >> t >> c1 >> cr;
  100.         if (t == 'P') {
  101.             if (c1 == cr) cout << R-1 << " 1\n";
  102.             else cout << "0 0\n";
  103.         } else if (t == 'R') {
  104.             if (c1 == cr) cout << "1 1\n";
  105.             else cout << "2 2\n";
  106.         } else if (t == 'Q') {
  107.             if (c1 == cr || sameDiagonal(1, c1, R, cr)) cout << "1 1\n";
  108.             else { // 2 moves
  109.                 int ways = 2 + 2; // Rook Rook, vertical Rook and Bishop (or vice versa)
  110.                 if (R == C && (c1 == 1 || c1 == C)) ++ways; // bishop + horizontal rook move
  111.                 if (R == C && (cr == 1 || cr == C)) ++ways; // horizontal rook move + bishop
  112.                 // both bishop moves:
  113.                 if (sameColor(1, c1, R, cr)) {
  114.                     auto [x1, y1] = diagonalIntersect(1, c1, R, cr);
  115.                     if (inBoard(x1, y1)) ++ways;
  116.                     auto [x2, y2] = diagonalIntersect(R, cr, 1, c1);
  117.                     if (inBoard(x2, y2)) ++ways;
  118.                 }
  119.                 cout << "2 " << ways << '\n';
  120.             }
  121.         } else if (t == 'B') {
  122.             pair<int, int> a = solveBishop(c1, cr), b = solveBishop(C+1-c1, C+1-cr);
  123.             auto [m, w] = combine(a, b);
  124.             if (m == INF) cout << "0 0\n";
  125.             else cout << m << ' ' << w << '\n';
  126.         } else { // t == 'K'
  127.             auto [m, w] = solveKing(c1, cr);
  128.             if (m == INF) cout << "0 0\n";
  129.             else cout << m << ' ' << w << '\n';
  130.         }
  131.     }
  132.     return 0;
  133. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement