版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82707184
初看这题时,觉得应该就是一个大爆搜,然后调了半天也没调出来
看了下题解才猛然醒悟…
题解:
容易发现,移动方块就是移动空格。这样的话,整个地图中就只有空格及其旁边的块才能移动。因此,我们预处理出每一个块向四周移动的步数,即每个方块某个方向的空格移动到另一个方向的步数。用
表示。注意:在空格移动时,不能经过当前块。因为如果经过了,当前块就会与空格交换位置,要交换回来必须再在原来的位置交换一次,这样又回到了原点。求最短距离就用BFS,我们不妨在求路径的时候直接把当前块标记为不可移动。
然后,我们把移动的过程抽象成一张图。当前块和空格交换位置,其实就是两个状态之间的转移。即:从当前块空格在p方向的状态转移到下一个块在p反方向的状态。转移的花费就相当于边的长度。
之后,就可以用SPFA跑最短路了。
注意细节及初状态处理,比如空格一开始的位置不一定在当前块旁边,要再跑一边BFS,求出一开始的距离
以后变量名一定要准确地表意。。
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 35;
const int MAXM = 35;
const int INF = 0x3f3f3f3f;
int n, m, q;
int Plate[MAXN][MAXM], Dis[MAXN][MAXM];
int vis[MAXN][MAXM][4], dis[MAXN][MAXM][4];
int State[MAXN][MAXM][4][4]; //目标棋子在i,j时,空白块从p1方向移动到p2方向的距离
int movex[] = {0, 0, 1, -1}, movey[] = {1, -1, 0, 0};
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
void Bfs(int ux, int uy){
queue<pair<int, int> > q; q.push(make_pair(ux, uy));
memset(Dis, 0x3f, sizeof(Dis)); Dis[ux][uy] = 0;
while(!q.empty()){
ux = q.front().first, uy = q.front().second; q.pop();
for(int p = 0; p < 4; p++){
int vx = ux + movex[p], vy = uy + movey[p];
if(Plate[vx][vy] && Dis[vx][vy] == INF){ //可以走
Dis[vx][vy] = Dis[ux][uy] + 1;
q.push(make_pair(vx, vy));
}
}
}
}
void PreWork(){
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(Plate[i][j]){
Plate[i][j] = 0;
for(int p1 = 0; p1 < 4; p1++) if(Plate[i + movex[p1]][j + movey[p1]]){
Bfs(i + movex[p1], j + movey[p1]);
for(int p2 = 0; p2 < 4; p2++) if(Plate[i + movex[p2]][j + movey[p2]]){
State[i][j][p1][p2] = State[i][j][p2][p1] = Dis[i + movex[p2]][j + movey[p2]];
}
}
Plate[i][j] = 1;
}
}
void SPFA(int ux, int uy){
queue<int> q1; queue<pair<int, int> > q;
memset(vis, false, sizeof(vis));
int pos;
for(int p = 0; p < 4; p++){
q.push(make_pair(ux, uy));
q1.push(p);
vis[ux][uy][p] = true;
}
while(!q.empty()){
ux = q.front().first, uy = q.front().second; q.pop();
pos = q1.front(); q1.pop();
vis[ux][uy][pos] = false;
for(int p = 0; p < 4; p++){
int vx = ux + movex[p], vy = uy + movey[p];
if(Plate[vx][vy]){ //可以走
int D = State[ux][uy][pos][p] + 1;
if(dis[vx][vy][p ^ 1] > dis[ux][uy][pos] + D){
dis[vx][vy][p ^ 1] = dis[ux][uy][pos] + D;
if(!vis[vx][vy][p ^ 1]){
vis[vx][vy][p ^ 1] = true;
q.push(make_pair(vx, vy));
q1.push(p ^ 1);
}
}
}
}
}
}
int main(){
freopen("in.txt", "r", stdin);
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d", &Plate[i][j]);
PreWork();
int ex, ey, sx, sy, tx, ty;
for(int i = 1; i <= q; i++){
scanf("%d%d%d%d%d%d", &ex, &ey, &sx, &sy, &tx, &ty);
if(sx == tx && sy == ty){puts("0"); continue;}
memset(dis, 0x3f, sizeof(dis));
Plate[sx][sy] = 0;
Bfs(ex, ey);
for(int p = 0; p < 4; p++){
int vx = sx + movex[p], vy = sy + movey[p];
if(Plate[vx][vy]) dis[sx][sy][p] = Dis[vx][vy];
}
Plate[sx][sy] = 1;
SPFA(sx, sy);
int Ans = INF;
for(int p = 0; p < 4; p++) Ans = min(Ans, dis[tx][ty][p]);
if(Ans == INF) puts("-1");
else printf("%d\n", Ans);
}
return 0;
}
update:发现数组开小了,同时加了点优化