[NOIP2013提高组]华容道
这道题第一眼看是暴力,然后发现直接暴力会TLE。
把问题转换一下:移动空格到处跑,如果空格跑到指定位置的棋子,交换位置。
这个可以设计一个状态:$[x1][y1][x2][y2]$,表示空格在$(x1,\ y1)$,棋子在$(x2,\ y2)$的状态,可以向四个方向进行转移。
直接转移,对于每一组询问,都要用 $O(n^4)$ 的时间处理,所以复杂度是 $O(n^4 \times q)$。$70pts$。
观察发现有很多状态是无用状态,只有指定棋子的上下左右四个位置的状态有价值。
然后建个图,会发现不需要在询问时处理,跑一遍最短路,即可AC。
复杂度:$O(n^4)\ +\ O(n^2\ logn \times q)$
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 6 using namespace std; 7 8 #define re register 9 #define LL long long 10 #define rep(i, x, y) for (register int i = x; i <= y; ++i) 11 #define repd(i, x, y) for (register int i = x; i >= y; --i) 12 #define maxx(a, b) a = max(a, b) 13 #define minn(a, b) a = min(a, b) 14 #define inf 1e9 15 #define linf 1e17 16 17 inline int read() { 18 re int w = 0, f = 1; char c = getchar(); 19 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 20 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ 48), c = getchar(); 21 return w * f; 22 } 23 24 const int maxn = 30 + 5; 25 26 struct State { 27 int x, y, d; 28 }; 29 30 queue<State> q; 31 32 struct Edge { 33 int u, v, w, pre; 34 }; 35 36 inline int convert(int x, int y, int d) { 37 return x * 120 + y * 4 + d; 38 } 39 40 struct Node { 41 int u, d; 42 bool operator < (const Node &rhs) const { 43 return d > rhs.d; 44 } 45 }; 46 47 priority_queue <Node> Q; 48 49 struct Graph { 50 Edge edges[maxn * maxn * maxn]; 51 int G[maxn * maxn * maxn], n, m; 52 int d[maxn * maxn * maxn], vis[maxn * maxn * maxn]; 53 void init(int n) { 54 this->n = n; 55 m = 0; 56 memset(G, 0, sizeof(G)); 57 } 58 void AddEdge(int u, int v, int w) { 59 edges[++m] = (Edge){u, v, w, G[u]}; 60 G[u] = m; 61 } 62 void dijkstra() { 63 memset(vis, 0, sizeof(vis)); 64 while (!Q.empty()) { 65 re Node head = Q.top(); Q.pop(); 66 int u = head.u; 67 if (vis[u]) continue; 68 vis[u] = 1; 69 for (re int i = G[u]; i; i = edges[i].pre) { 70 Edge &e = edges[i]; 71 if (!vis[e.v] && d[u] + e.w < d[e.v]) { 72 d[e.v] = d[u] + e.w; 73 Q.push((Node){e.v, d[e.v]}); 74 } 75 } 76 } 77 } 78 } G; 79 80 int fx[4] = {0, 1, 0, -1}; 81 int fy[4] = {1, 0, -1, 0}; 82 83 int n, m, t; 84 int a[maxn][maxn], vis[maxn][maxn], dis[maxn][maxn]; 85 86 void bfs(int X, int Y) { 87 memset(dis, 0x3f, sizeof(dis)); 88 dis[X][Y] = 0; 89 q.push((State){X, Y, 0}); 90 while (!q.empty()) { 91 State head = q.front(); q.pop(); 92 dis[head.x][head.y] = head.d; 93 rep(i, 0, 3) { 94 re int x = head.x + fx[i], y = head.y + fy[i]; 95 if (a[x][y] && !vis[x][y]) { 96 vis[x][y] = 1; 97 dis[x][y] = head.d + 1; 98 q.push((State){x, y, dis[x][y]}); 99 } 100 } 101 } 102 } 103 104 int main() { 105 n = read(), m = read(), t = read(); 106 107 rep(i, 1, n) 108 rep(j, 1, m) 109 a[i][j] = read(); 110 111 G.init(n * n * 4); 112 113 rep(X, 1, n) 114 rep(Y, 1, m) 115 if (a[X][Y]) { 116 rep(i, 0, 3) { 117 re int x = X + fx[i], y = Y + fy[i]; 118 if (a[x][y]) { 119 memset(vis, 0, sizeof(vis)); 120 vis[x][y] = vis[X][Y] = 1; 121 bfs(x, y); 122 rep(j, 0, 3) { 123 re int x2 = X + fx[j], y2 = Y + fy[j]; 124 if (i == j || !a[x2][y2]) continue; 125 G.AddEdge(convert(X, Y, i), convert(X, Y, j), dis[x2][y2]); 126 } 127 } 128 } 129 if (a[X][Y + 1]) G.AddEdge(convert(X, Y, 0), convert(X, Y + 1, 2), 1); 130 if (a[X + 1][Y]) G.AddEdge(convert(X, Y, 1), convert(X + 1, Y, 3), 1); 131 if (a[X][Y - 1]) G.AddEdge(convert(X, Y, 2), convert(X, Y - 1, 0), 1); 132 if (a[X - 1][Y]) G.AddEdge(convert(X, Y, 3), convert(X - 1, Y, 1), 1); 133 } 134 135 re int Ex, Ey, Sx, Sy, Tx, Ty; 136 137 while (t--) { 138 Ex = read(), Ey = read(), Sx = read(), Sy = read(), Tx = read(), Ty = read(); 139 140 if (Sx == Tx && Sy == Ty) { 141 printf("0\n"); 142 continue; 143 } 144 145 memset(vis, 0, sizeof(vis)); 146 vis[Ex][Ey] = vis[Sx][Sy] = 1; 147 bfs(Ex, Ey); 148 memset(G.d, 0x3f, sizeof(G.d)); 149 rep(i, 0, 3) { 150 Q.push((Node){convert(Sx, Sy, i), dis[Sx + fx[i]][Sy + fy[i]]}); 151 G.d[convert(Sx, Sy, i)] = dis[Sx + fx[i]][Sy + fy[i]]; 152 } 153 G.dijkstra(); 154 155 re int ans = inf; 156 rep(i, 0, 3) 157 if (a[Tx + fx[i]][Ty + fy[i]]) minn(ans, G.d[convert(Tx, Ty, i)]); 158 if (ans == inf) printf("-1\n"); 159 else printf("%d\n", ans); 160 } 161 162 return 0; 163 }