8
1
2015
1

【BFS预处理+最短路】NOIP2013 T6华容道

自古T6码农题【雾】自古六面出忠臣!

奇葩改编华容道(更TM像八数码好么)

初始思路:大力BFS!(考虑只需要记录空格与需移动点的状态)

目测60分,TLE(其实我并没有写过,SHC神犇说可以加个启发式或是双向【双向A*BFS】;老板娘说可以随机化模拟退火)

因为可移动棋子一定要空格在边上才能动,所以肯定先要做一个最短路从空格到棋子,然后空格滚到棋子的另一边才能移动。

关键是q次询问都在同一个图里!

预处理预处理?预处理预处理!

以空格靠在棋子某个方向为状态点,构图。算出每个点相邻四格互相移动的步数,连边。空格和棋子交换(即棋子挪动)也连边,权为1。

以超级起点(初始空格)跑到棋子四周的距离连边,目标终点四周与超级终点连边,边权为0,跑最短路。

Code似乎写得长了点QAQ

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define maxv 32
#define maxn 3600
#define maxm 30000
#define INF 2000000000
using namespace std;
struct Edge
{
	int fr,to,d;
};
struct poi
{
	int x,y;
};
int ST[4][2]={{0,-1},{-1,0},{1,0},{0,1}};
int a[maxv][maxv],r,c,q;//row,column
int dir[maxv][maxv][4];//上下左右点号
int GO[maxv][maxv][4][4];
int b[maxv][maxv];
//0-L,1-U,2-D,3-R
queue <poi> Q;
int dd[maxv][maxv];
void BFS2(poi S,int* ans,int xx,int yy)//空格从某方向移至另一方向
{
	memset(b,0,sizeof(b));
	
	Q.push(S);
	b[S.x][S.y]=1;
	for (int i=0;i<=r+1;i++)
		for (int j=0;j<=c+1;j++)
			dd[i][j]=INF;
	dd[S.x][S.y]=0;
	poi n;
	while (!Q.empty())
	{
		n=Q.front();
		Q.pop();
		for (int i=0;i<4;i++)
		{
			int x=n.x+ST[i][0],y=n.y+ST[i][1];
			if (!a[x][y]) continue;
			if (b[x][y]) continue;
			Q.push((poi){x,y});
			b[n.x][n.y]=1;
			dd[x][y]=dd[n.x][n.y]+1;
		}
	}
	for (int i=0;i<4;i++)
		ans[i]=dd[xx+ST[i][0]][yy+ST[i][1]];
}
int n=0,m=0;
Edge es[maxm];
int next[maxm],first[maxn],dis[maxn],inq[maxn],ww[4];
queue <int> S;
void AddEdge(int f,int t,int w)
{
	m++;
	es[m]=(Edge){f,t,w};
	next[m]=first[f];
	first[f]=m;
}
void DelEdge(int f)
{
	first[f]=next[first[f]];
	m--;
}
int SPFA(int s,int t)
{
	for (int i=0;i<=n;i++)
		dis[i]=INF;
	dis[s]=0;
	S.push(s);
	inq[s]=1;
	while (!S.empty())
	{
		int u=S.front();
		S.pop();
		inq[u]=0;
		for (int i=first[u];i!=-1;i=next[i])
		{
			Edge e=es[i];
			if (dis[e.to]>dis[u]+e.d)
			{
				dis[e.to]=dis[u]+e.d;
				if (!inq[e.to])
				{
					inq[e.to]=1;
					S.push(e.to);
				}
			}
		}
	}
	if (dis[n]==INF) return -1;
	return dis[n];
}
int main()
{
	scanf("%d%d%d",&r,&c,&q);
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
			scanf("%d",&a[i][j]);
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
		{
			if (!a[i][j]) continue;
			for (int k=0;k<4;k++)
			{
				int x=i+ST[k][0],y=j+ST[k][1];
				if (!a[x][y]) continue;
				dir[i][j][k]=++n;
			}
		}
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
			if (a[i][j])	
			{
				a[i][j]=0;
				for (int k=0;k<4;k++)
					if (dir[i][j][k])
					{
						BFS2((poi){i+ST[k][0],j+ST[k][1]},ww,i,j);
						for (int l=0;l<4;l++)
							GO[i][j][k][l]=ww[l];
					}
				a[i][j]=1;	
			}
	n++;//0:Start n+1:Terminal
	for (int i=0;i<=n;i++)
		first[i]=-1;
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
		{
			if (!a[i][j]) continue;
			for (int k=0;k<4;k++)
			{
				int x=i+ST[k][0],y=j+ST[k][1];
				if (!a[x][y]) continue;
				AddEdge(dir[i][j][k],dir[x][y][3-k],1);
			}
		}
	for (int i=1;i<=r;i++)
		for (int j=1;j<=c;j++)
			if (a[i][j])
				for (int k=0;k<4;k++)
					if (dir[i][j][k])
						for (int l=0;l<4;l++)
							if (dir[i][j][l])
								if (k!=l) 
									if (GO[i][j][k][l]!=INF)
										AddEdge(dir[i][j][k],dir[i][j][l],GO[i][j][k][l]);
	for (int i=1;i<=q;i++)
	{
		int Ex,Ey,Sx,Sy,Tx,Ty;
		scanf("%d%d%d%d%d%d",&Ex,&Ey,&Sx,&Sy,&Tx,&Ty);
		if (!(a[Sx][Sy]&&a[Tx][Ty])) 
		{
			printf ("-1\n");
			continue;
		} 
		if (Ex==Sx&&Ey==Sy)
		{
			printf ("-1\n");
			continue;
		} 
		if (Tx==Sx&&Ty==Sy)
		{
			printf("0\n");
			continue;
		} 
		a[Sx][Sy]=0;
		BFS2((poi){Ex,Ey},ww,Sx,Sy);
		a[Sx][Sy]=1;
		
		for (int k=0;k<4;k++)
			if (dir[Sx][Sy][k]) AddEdge(0,dir[Sx][Sy][k],ww[k]);
		for (int k=0;k<4;k++)
			if (dir[Tx][Ty][k]) AddEdge(dir[Tx][Ty][k],n,0);
		printf("%d\n",SPFA(0,n));
		for (int k=3;k>=0;k--)
			if (dir[Tx][Ty][k]) DelEdge(dir[Tx][Ty][k]);
		for (int k=3;k>=0;k--)
			if (dir[Sx][Sy][k]) DelEdge(0);
		
	}
	return 0;
}

祝贺CCF在IOI上被打脸*1,OI目前起源于韩国。

Category: NOIP | Tags: BFS 最短路 | Read Count: 923
Avatar_small
orz hhw 说:
2015年8月25日 14:15

%%%最短路大师
而且这题裸暴力是75分吧,加个IDA*/双向没准AC了呢


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com