关于华容道:
算法一:bfs暴搜
用空格坐标和目标格子坐标作为图的代表用bool数组判重(高性价比)
得分:60;
算法二:最短路
省去每遍bfs重复搜索的部分 方法:记录某格子在方格位于其k方向时向方向h移动一步所需步数(用bfs求出空格从k方向移动到h的反方向所需的步数) 记录在一个四位数组Go中; (注意 因为bfs将空格直接调整到目标格子当前的h 的反方向 在调整过程中都不能移动目标格子 所以在bfs之前将目标格子位置的状态设置为不可用)
定义一个状态:某方格的k方向为空格 用全局变量V对每一个状态编号 对于该方格 若其能移动到h方向则把两个状态加边(注意两个状态中的空格方向的处理)
对于每一个读入的初始点 定义一个新的状态编号S(因为目标格子周围不一定有空格 不能用已编好的编号进行对映) 用bfs求出将空格子移动到目标格子上下左右四个方向所需要的步数 并将S与其连边
同理 对于每一个目标点 定义一个新的状态编号T 将其与周围四个格子连边(连边时周围格子的空格方位是目标格子)
用SPFA求出由S到T的最短路径即可;
#include
#include
#include
#include
using namespace std;
#define MAXN 30
#define MAXP 100000
#define INF (1 << 25)
using namespace std;
struct Node{
int v, wt;
Node *next;
}Edge[MAXP*2+10];
Node *adj[MAXP+10];
Node *ecnt = &Edge[0];
struct node{
int x, y;
};
int cx[] = {-1, 1, 0, 0};
int cy[] = {0, 0, -1, 1};
int sx, sy, ex, ey, tx, ty;
int n, m, ma[MAXN+10][MAXN+10], A[MAXN+10][MAXN+10][5], q, d[MAXN+10][MAXN+10], dis[MAXP+10], Go[MAXN+10][MAXN+10][5][5], V, S, T;
bool vis[MAXP+10];
void addedge(int u, int v, int wt)
{
Node *p = ++ecnt;
p->v = v;
p->wt = wt;
p->next = adj[u];
adj[u] = p;
}
int bfs(int sx, int sy, int tx, int ty)
{
if(sx == tx && sy == ty)
return 0;
queue q;
while(!q.empty())
q.pop();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
d[i][j] = INF;
d[sx][sy] = 0;
node a;
a.x = sx;
a.y = sy;
q.push(a);
while(!q.empty())
{
a = q.front();q.pop();
int x = a.x;
int y = a.y;
for(int i = 0; i < 4; i++)
{
int xx = x + cx[i];
int yy = y + cy[i];
if(ma[xx][yy] && d[xx][yy] == INF)
{
d[xx][yy] = d[x][y] + 1;
if(xx == tx && yy == ty)
return d[x][y]+1;
a.x = xx;
a.y = yy;
q.push(a);
}
}
}
return INF;
}
struct cmp{
bool operator()(int a, int b)
{
return dis[a] > dis[b];
}
};
/*priority_queue , cmp> Q;
int SPFA()
{
for(int i = 1; i <= V; i++)
dis[i] = INF; // slower
while(!Q.empty())
Q.pop();
dis[S] = 0;
memset(vis, true, sizeof(vis));
Q.push(S);
while(!Q.empty())
{
int u = Q.top();
Q.pop();
if(!vis[u])
continue;
vis[u] = false;
if(u == T)
return dis[T];
for(Node *p = adj[u]; p; p = p->next)
{
int v = p->v;
if(dis[v] > dis[u] + p->wt)
{
dis[v] = dis[u] + p->wt;
Q.push(v);
vis[v] = true;
}
}
}
return dis[T] < INF ? dis[T] : -1;
}*/
queue Q;
int SPFA()
{
for(int i = 1; i <= V; i++) // faster
dis[i] = INF;
while(!Q.empty())
Q.pop();
dis[S] = 0;
memset(vis, 0, sizeof(vis));
Q.push(S);
vis[S] = true;
while(!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = false;
for(Node *p = adj[u]; p; p = p->next)
{
int v = p->v;
if(dis[v] > dis[u] + p->wt)
{
dis[v] = dis[u] + p->wt;
if(!vis[v])
{
Q.push(v);
vis[v] = true;
}
}
}
}
return dis[T] < INF ? dis[T] : -1;
}
void init()
{
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
for(int k = 0;k < 4; k++)
for(int h = 0; h < 4; h++)
Go[i][j][k][h] = INF;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(ma[i][j])
{
ma[i][j] = 0;
for(int k = 0; k < 4; k++)
if(ma[i+cx[k]][j+cy[k]])
{
for(int h = 0; h < 4; h++)
if(ma[i+cx[h]][j+cy[h]])
Go[i][j][k][h] = bfs(i + cx[k], j + cy[k], i + cx[h], j + cy[h])+1;
}
ma[i][j] = 1;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
for(int k = 0;k < 4; k++)
for(int h = 0; h < 4; h++)
if(Go[i][j][k][h] != INF)
addedge(A[i][j][k], A[i+cx[h]][j+cy[h]][h^1], Go[i][j][k][h]);
}
void solve()
{
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)
{
printf("0\n");
continue;
}
if((ma[sx][sy] == 0) || (ma[tx][ty] == 0))
{
printf("-1\n");
continue;
}
S = ++V;
T = ++V;
ma[sx][sy] = 0;
for(int i = 0; i < 4; i++)
if(ma[sx+cx[i]][sy+cy[i]])
{
int Dis = bfs(ex, ey, sx+cx[i], sy+cy[i]);
if(Dis != INF)
addedge(S, A[sx][sy][i], Dis);
}
ma[sx][sy] = 1;
for(int i = 0; i < 4; i++)
if(ma[tx+cx[i]][ty+cy[i]])
addedge(A[tx][ty][i], T, 0);
printf("%d\n", SPFA());
}
}
int main()
{
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
scanf("%d", &ma[i][j]);
for(int k = 0; k < 4; k++)
A[i][j][k] = ++V;
}
init();
solve();
}