bzoj 1644: [Usaco2007 Oct]Obstacle Course 障碍训练课 (spfa)

本文介绍了一道USACO竞赛题目的解决方案,题目名为“障碍训练课”。任务是在一个NxN的网格中找到从起点A到终点B的路径,使得转弯次数最少。通过使用SPFA算法并考虑不同方向的移动来解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1644: [Usaco2007 Oct]Obstacle Course 障碍训练课

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 573   Solved: 276
[ Submit][ Status][ Discuss]

Description

考虑一个 N x N (1 <= N <= 100)的有1个个方格组成的正方形牧场。有些方格是奶牛们不能踏上的,它们被标记为了'x'。例如下图:

. . B x .
. x x A .
. . . x .
. x . . .
. . x . .

贝茜发现自己恰好在点A处,她想去B处的盐块舔盐。缓慢而且笨拙的动物,比如奶牛,十分讨厌转弯。尽管如此,当然在必要的时候她们还是会转弯的。对于一个给定的牧场,请你计算从A到B最少的转弯次数。开始的时候,贝茜可以使面对任意一个方向。贝茜知道她一定可以到达。

Input

第 1行: 一个整数 N 行

2..N + 1: 行 i+1 有 N 个字符 ('.', 'x', 'A', 'B'),表示每个点的状态。

Output

行 1: 一个整数,最少的转弯次数。

Sample Input

3
.xA
...
Bx.

Sample Output

2

HINT

Source

[ Submit][ Status][ Discuss]


题解:spfa

注意记录不同方向的答案即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 103
#define pa pair<int,int>
using namespace std;
int n,m,sx,sy,tx,ty;
int map[N][N],dis[N][N][5],can[N][N][5];
int px[10]={0,1,0,-1},py[10]={1,0,-1,0};
struct data {
	int x,y,pos;
};
char s[N];
void spfa()
{
	queue<data> p;
	memset(dis,127,sizeof(dis));
	memset(can,0,sizeof(can));
	for (int i=0;i<4;i++){
		int nowx=sx+px[i]; int nowy=sy+py[i];
		if (nowx<=0||nowy<=0||nowx>n||nowy>n||map[nowx][nowy]) continue;
	    can[nowx][nowy][i]=1; dis[nowx][nowy][i]=0;
		data a; a.x=nowx; a.y=nowy; a.pos=i;
		p.push(a);
	}
	while(!p.empty()) {
		data now=p.front(); p.pop();
		int x=now.x; int y=now.y;
		for (int i=0;i<4;i++) {
			int nowx=x+px[i]; int nowy=y+py[i];
			if (nowx<=0||nowy<=0||nowx>n||nowy>n||map[nowx][nowy]) continue;
			if(dis[nowx][nowy][i]>dis[x][y][now.pos]+(now.pos==i?0:1)) {
				dis[nowx][nowy][i]=dis[x][y][now.pos]+(now.pos==i?0:1);
				if (!can[nowx][nowy][i]) {
					can[nowx][nowy][i]=1;
					data a; a.x=nowx; a.y=nowy; a.pos=i;
		            p.push(a);
				}
			}
		} 
		can[x][y][now.pos]=0;
	}
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) {
		scanf("%s",s+1);
		for (int j=1;j<=n;j++) 
		 {
		 	if (s[j]=='B') tx=i,ty=j;
		 	if (s[j]=='A') sx=i,sy=j;
		 	if (s[j]=='x') map[i][j]=1;
		 }
	}
	//cout<<sx<<" "<<sy<<" "<<tx<<" "<<ty<<endl;
	spfa();
	int ans=1000000000;
	for (int i=0;i<4;i++) ans=min(ans,dis[tx][ty][i]);
	printf("%d\n",ans);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值