题目链接,我觉得这是一道好题~ 题解戳这里
首先,要移动指定棋子,必定要将空格移到它的邻近方格。
然后,我们有两个决策:
按这个方式构图,跑最短路就可以了。
这个图比较稀疏,SPFA 是可以解决的 (来卡我啊)。
当然还有一个需要特殊判断的情形: 方格的起始位置与结束位置相同。
时间复杂度: O((N∗M)2+q∗(N∗M))
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
templatevoid read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
}
templatevoid write(Num x)
{
if(!x) {putchar('0');return;}
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
while(sl) putchar(s[--sl]);
}
const int maxn = 35, maxm = 35, inf = 0x3f3f3f3f, nya = -1;
const int vec[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
const int node = maxn * maxm << 2, edgenum = node << 2;
int n, m, q;
int ex, ey, sx, sy, tx, ty;
int map[maxn][maxm];
struct Edge
{
int v, w, next;
Edge(int v = 0,int w = 0,int next = 0):v(v), w(w), next(next){};
};
int head[node], el, _head[node], _el;
Edge edge[edgenum];
int ind, S, T;
#define index(x, y, p) (((((x) - 1)*m + ((y) - 1))<<2) + (p) + 1)
#define table(x, y) (((x) - 1)*m + (y))
#define getx(S) (((S) - 1)/m + 1)
#define gety(S) (((S) - 1)%m + 1)
void newedge(int u,int v,int w)
{
edge[++el] = Edge(v, w, head[u]), head[u] = el;
}
int BFS(int fx,int fy,int dx,int dy,int bx,int by)
{
if(!map[fx][fy] || fx == bx && fy == by) return inf;
if(!map[dx][dy] || dx == bx && dy == by) return inf;
static int line[maxn * maxm], dist[maxn * maxm];
int f = 0, r = 0, e, p, px, py;
for(int i = 1; i <= n*m; i++) dist[i] = nya;
line[r++] = table(fx, fy), dist[table(fx, fy)] = 0;
while(f != r)
{
if((e = line[f++]) == table(dx, dy)) return dist[e];
for(int i = 0; i < 4; i++)
{
px = getx(e) + vec[i][0], py = gety(e) + vec[i][1];
if(px == bx && py == by) continue;
if(dist[p = table(px, py)] == nya && map[px][py])
line[r++] = p, dist[p] = dist[e] + 1;
}
}
return inf;
}
int SPFA()
{
static int line[node], dist[node];
static bool hash[node];
int f = 0, r = 0;
for(int i = 1; i <= ind; i++)
dist[i] = inf, hash[i] = false;
dist[S] = 0, line[r] = S, r = (r + 1)%node;
hash[S] = true;
while(f != r)
{
int e = line[f], p;
f = (f + 1)%node;
hash[e] = false;
for(int i = head[e]; i ; i = edge[i].next)
{
int tmp = dist[e] + edge[i].w;
if(tmp < dist[p = edge[i].v])
{
dist[p] = tmp;
if(!hash[p])
{
if(dist[p] <= dist[line[f]])
f = (f - 1 + node) % node, line[f] = p;
else
line[r] = p, r = (r + 1) % node;
hash[p] = true;
}
}
}
}
return dist[T] < inf ? dist[T] : nya;
}
void prework()
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if(!map[i][j]) continue;
for(int k = 0; k < 4; k++)
{
if(!map[i + vec[k][0]][j + vec[k][1]]) continue;
for(int h = 0; h < 4; h++)
if(k != h)
{
int cost = BFS(i + vec[k][0], j + vec[k][1], i + vec[h][0], j + vec[h][1], i, j);
if(cost < inf) newedge(index(i, j, k), index(i, j, h), cost);
}
newedge(index(i, j, k), index(i + vec[k][0], j + vec[k][1], k ^ 1), 1);
}
}
S = (n * m << 2) + 1;
T = ind = S + 1;
for(int i = 1; i <= ind; i++) _head[i] = head[i];
_el = el;
}
void init()
{
read(n), read(m), read(q);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
read(map[i][j]);
}
void solve()
{
read(ex), read(ey);
read(sx), read(sy), read(tx), read(ty);
if(sx == tx && sy == ty)
{
puts("0");
return;
}
for(int i = 1; i <= ind; i++) head[i] = _head[i];
el = _el;
for(int i = 0; i < 4; i++)
{
int cost = BFS(ex, ey, sx + vec[i][0], sy + vec[i][1], sx, sy);
if(cost < inf) newedge(S, index(sx, sy, i), cost);
if(map[tx + vec[i][0]][ty + vec[i][1]])
newedge(index(tx, ty, i), T, 0);
}
write(SPFA()), puts("");
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("puzzle.in","r",stdin);
freopen("puzzle.out","w",stdout);
#endif
init(), prework();
while(q--) solve();
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}