[关闭]
@ZCDHJ 2019-10-27T23:44:24.000000Z 字数 1993 阅读 452

Codeforces375C Circling Round Treasures

未分类


首先要知道咋判断一个点是否在一个多边形里面:做一条不穿过任意多边形顶点的射线,如果经过的边数为奇数则在多边形里面,反之在外面。

咋造不穿过方格里任意点的射线呢?选一个趋于负无穷的斜率就行了。那么状压 DP,设 为走到点 为宝藏的包含状态时的最短路。用 BFS 来转移。

对于炸弹,将它看成一个收益为负无穷的宝藏就行了。注意这个值不能太小,不然会溢出。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <queue>
  4. #include <cstring>
  5. const int MAXN = 200;
  6. const int NXT[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
  7. int n, m, sx, sy, tot;
  8. int dp[MAXN | 1][MAXN | 1][1 << 8];
  9. char s[MAXN + 5][MAXN + 5];
  10. struct Dot {
  11. int x, y, val;
  12. Dot() : x(0), y(0), val(0) {}
  13. Dot(int _x, int _y, int _val) : x(_x), y(_y), val(_val) {}
  14. } a[10];
  15. struct Queue {
  16. int x, y, z;
  17. Queue() : x(0), y(0), z(0) {}
  18. Queue(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
  19. };
  20. std::queue < Queue > q;
  21. inline int read() {
  22. register int x = 0, v = 1;
  23. register char ch = getchar();
  24. while (!isdigit(ch)) {
  25. if (ch == '-') v = -1;
  26. ch = getchar();
  27. }
  28. while (isdigit(ch)) {
  29. x = x * 10 + ch - '0';
  30. ch = getchar();
  31. }
  32. return x * v;
  33. }
  34. int calc(int _x0, int _y0, int _x1, int _y1, int i) {
  35. if (_x0 == a[i].x && _y0 > a[i].y) return _x1 < a[i].x;
  36. if (_x1 == a[i].x && _y1 > a[i].y) return _x0 < a[i].x;
  37. return 0;
  38. }
  39. int DP() {
  40. memset(dp, -1, sizeof(dp));
  41. q.push(Queue(sx, sy, 0));
  42. dp[sx][sy][0] = 0;
  43. do {
  44. Queue from = q.front();
  45. q.pop();
  46. for (int k = 0; k < 4; ++k) {
  47. int tx = from.x + NXT[k][0], ty = from.y + NXT[k][1];
  48. if (tx < 1 || tx > n || ty < 1 || ty > m || (s[tx][ty] != '.' && s[tx][ty] != 'S')) continue;
  49. int tmp = from.z;
  50. for (int i = 1; i <= tot; ++i) {
  51. tmp ^= (calc(from.x, from.y, tx, ty, i) << (i - 1));
  52. }
  53. if (dp[tx][ty][tmp] == -1 || dp[tx][ty][tmp] == 0) {
  54. dp[tx][ty][tmp] = dp[from.x][from.y][from.z] + 1;
  55. q.push(Queue(tx, ty, tmp));
  56. }
  57. }
  58. } while (!q.empty());
  59. int ans = 0;
  60. for (int i = 1; i < (1 << tot); ++i) {
  61. int sum = 0;
  62. if (dp[sx][sy][i] == -1) continue;
  63. for (int j = 1; j <= tot; ++j) {
  64. if (((i >> (j - 1)) & 1) == 1) {
  65. sum += a[j].val;
  66. }
  67. }
  68. if (sum - dp[sx][sy][i] > ans) {
  69. ans = sum - dp[sx][sy][i];
  70. }
  71. }
  72. return ans;
  73. }
  74. int main() {
  75. freopen("code.in", "r", stdin);
  76. freopen("code.out", "w", stdout);
  77. n = read();
  78. m = read();
  79. for (int i = 1; i <= n; ++i) {
  80. scanf("%s", s[i] + 1);
  81. }
  82. for (int i = 1; i <= n; ++i) {
  83. for (int j = 1; j <= m; ++j) {
  84. if (s[i][j] == 'S') {
  85. sx = i;
  86. sy = j;
  87. }
  88. if (isdigit(s[i][j])) {
  89. a[s[i][j] - '0'] = Dot(i, j, 0);
  90. ++tot;
  91. }
  92. }
  93. }
  94. for (int i = 1; i <= tot; ++i) a[i].val = read();
  95. for (int i = 1; i <= n; ++i) {
  96. for (int j = 1; j <= m; ++j) {
  97. if (s[i][j] == 'B') {
  98. a[++tot] = Dot(i, j, -2e9 / 400);
  99. }
  100. }
  101. }
  102. printf("%d\n", DP());
  103. return 0;
  104. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注