bzoj 1644: [Usaco2007 Oct]Obstacle Course 障碍训练课【spfa】

洛谷的数据毒啊
把(i,j,k)作为一个点spfa,表示点(i,j)朝向k方向,然后向四个方向转移即可

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=105,inf=1e9,dx[]={-1,1,0,0},dy[]={0,0,-1,1};
int n,sx,sy,tx,ty,dis[N][N][5];
char a[N][N];
bool v[N][N][5];
struct qwe
{
	int x,y,k;
	qwe(int X=0,int Y=0,int K=0)
	{
		x=X,y=Y,k=K;
	}
};
inline bool ok(int x,int y)
{
	return x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]!='x';
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%s",a[i]+1);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			if(a[i][j]=='A')
				sx=i,sy=j;
			if(a[i][j]=='B')
				tx=i,ty=j;
			for(int k=0;k<4;k++)
				dis[i][j][k]=inf;
		}//cerr<<sx<<" "<<sy<<"   "<<tx<<" "<<ty<<endl;
	queue<qwe>q;
	v[sx][sy][0]=1,v[sx][sy][1]=1,v[sx][sy][2]=1,v[sx][sy][3]=1;
	dis[sx][sy][0]=0,dis[sx][sy][1]=0,dis[sx][sy][2]=0,dis[sx][sy][3]=0;
	q.push(qwe(sx,sy,0)),q.push(qwe(sx,sy,1)),q.push(qwe(sx,sy,2)),q.push(qwe(sx,sy,3));
	while(!q.empty())
	{
		int x=q.front().x,y=q.front().y,k=q.front().k;
		q.pop();
		v[x][y][k]=0;
		for(int i=0;i<4;i++)
			if(ok(x+dx[i],y+dy[i])&&dis[x+dx[i]][y+dy[i]][i]>dis[x][y][k]+(k!=i))
			{
				dis[x+dx[i]][y+dy[i]][i]=dis[x][y][k]+(k!=i);
				if(!v[x+dx[i]][y+dy[i]][i])
				{
					v[x+dx[i]][y+dy[i]][i]=1;
					q.push(qwe(x+dx[i],y+dy[i],i));
				}
			}
	}
	// for(int i=1;i<=n;i++)
		// for(int j=1;j<=n;j++)
			// for(int k=0;k<4;k++)
				// cerr<<i<<" "<<j<<" "<<k<<" "<<dis[i][j][k]<<endl;
	printf("%d
",min(min(dis[tx][ty][0],dis[tx][ty][1]),min(dis[tx][ty][2],dis[tx][ty][3])));
	return 0;
}
/*
3
.xA
...
Bx.
*/
原文地址:https://www.cnblogs.com/lokiii/p/9012250.html