[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 }

 

转载于:https://www.cnblogs.com/ac-evil/p/9901635.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值