最短路变式+思维 [USACO07OCT]Obstacle Course S(洛谷 P1649)

[USACO07OCT]Obstacle Course S

题目描述

Consider an N x N (1 <= N <= 100) square field composed of 1

by 1 tiles. Some of these tiles are impassible by cows and are marked with an ‘x’ in this 5 by 5 field that is challenging to navigate:
图略:
Bessie finds herself in one such field at location A and wants to move to location B in order to lick the salt block there. Slow, lumbering creatures like cows do not like to turn and, of course, may only move parallel to the edges of the square field. For a given field, determine the minimum number of ninety degree turns in any path from A to B. The path may begin and end with Bessie facing in any direction. Bessie knows she can get to the salt lick.

N*N(1<=N<=100)方格中,’x’表示不能行走的格子,’.’表示可以行走的格子。卡门很胖,故而不好转弯。现在要从A点走到B点,请问最少要转90度弯几次?

输入格式

第一行一个整数N,下面N行,每行N个字符,只出现字符:’.’,’x’,’A’,’B’,表示上面所说的矩阵格子,每个字符后有一个空格。

【数据规模】

2<=N<=100

输出格式

一个整数:最少转弯次数。如果不能到达,输出-1。


这道题可以用bfs算出所有路径,然后求出所有路径的转弯次数最小的一条;

但是也可以直接求最短路,我用的是dij算法;

跟一般的最短路不同,这道题的最短路的写法不太一样,首先一个每个结点要带三个属性:

  1. 该结点坐标点x和y
  2. 该点的方向f
  3. 从起点走到该点的最少转向次数

最不同的是判断了,一般的最短路dij在判断是否该入队时一般是不打等号的,但是这个必须打,因为就算路径相同,该点的方向也可能不同,然后还有判断是否遍历过这个点,也是不同的;代码有注释;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
using namespace std;
const int N=10000100;
const int M=200100;
const LL mod=2e9+7;
char s[110][110];
int sx,sy,ex,ey,dis[110][110],n;
bool vis[110][110];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
struct Node{
	int x,y,w,f;
	bool operator < (const Node& rhs) const{return w>rhs.w;}
};
void dij(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++) dis[i][j]=2e9;
	}
	dis[sx][sy]=0;
	priority_queue<Node>qu;
	qu.push((Node){sx,sy,0,-1});
	while(!qu.empty()){
		Node n1=qu.top();
		qu.pop();
//		if(vis[n1.x][n1.y]) continue;//这个判断条件不能有 
		vis[n1.x][n1.y]=true;
		for(int i=0;i<=3;i++){
			int x=n1.x+dx[i];
			int y=n1.y+dy[i];
			if(x<1||x>n||y<1||y>n||s[x][y]=='x'||vis[x][y]) continue;
			if(n1.f==-1){
				dis[x][y]=1;
				qu.push((Node){x,y,1,i});
			}
			else{
				if(abs(n1.f-i)==2||n1.f==i){//不转向 
					if(dis[x][y]>=n1.w) dis[x][y]=n1.w,qu.push((Node){x,y,dis[x][y],i});
					//必须有等号 
				}
				else{//转向 
					if(dis[x][y]>=n1.w+1) dis[x][y]=n1.w+1,qu.push((Node){x,y,dis[x][y],i});
					//必须有等号 	
				}
			}
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>s[i][j];
			if(s[i][j]=='A') sx=i,sy=j;
			if(s[i][j]=='B') ex=i,ey=j;
		}
	}
	dij();
	if(dis[ex][ey]==2e9) cout<<-1<<endl;
	else cout<<dis[ex][ey]-1<<endl;
	return 0;
}

发布了264 篇原创文章 · 获赞 46 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_44291254/article/details/105347940
今日推荐