[NOIP2013]华容道

关于华容道:

算法一:bfs暴搜

      用空格坐标和目标格子坐标作为图的代表用bool数组判重(高性价比)

 得分:60

算法二:最短路

      省去每遍bfs重复搜索的部分 方法:记录某格子在方格位于其k方向时向方向h移动一步所需步数(用bfs求出空格从k方向移动到h的反方向所需的步数) 记录在一个四位数组Go中; (注意 因为bfs将空格直接调整到目标格子当前的的反方向 在调整过程中都不能移动目标格子 所以在bfs之前将目标格子位置的状态设置为不可用)

      定义一个状态:某方格的k方向为空格 用全局变量V对每一个状态编号 对于该方格 若其能移动到h方向则把两个状态加边(注意两个状态中的空格方向的处理)

      对于每一个读入的初始点 定义一个新的状态编号S(因为目标格子周围不一定有空格 不能用已编好的编号进行对映) 用bfs求出将空格子移动到目标格子上下左右四个方向所需要的步数 并将S与其连边 

      同理 对于每一个目标点 定义一个新的状态编号T  将其与周围四个格子连边(连边时周围格子的空格方位是目标格子)

      用SPFA求出由ST的最短路径即可;

#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();
}


你可能感兴趣的:([NOIP2013]华容道)