1. 程式人生 > >【JZOJ5793】小S練跑步【BFS】

【JZOJ5793】小S練跑步【BFS】

題目大意:

題目連結:https://jzoj.net/senior/#main/show/5793
題目圖片:
http://wx1.sinaimg.cn/mw690/0060lm7Tly1fvx7ksrc55j30j20dw3z4.jpg
http://wx3.sinaimg.cn/mw690/0060lm7Tly1fvx7kss9v0j30jb0g1jro.jpg


思路:

P.S.本蒟蒻的語文不好,對於很難簡化的題目起不到什麼簡化所用。各位dalao就看題目圖片吧QWQ


正題:

很裸的廣搜啊。。。
對於一個點,向四個方向搜,直到遇到不能走的位置在停下。
例如:
在這裡插入圖片描述
就往四個方向列舉,直到四個方向都走到底為止。
那麼上圖能走的(能轉移的)被標記成紅色就是:
在這裡插入圖片描述


這也就是和普通廣搜的區別吧。。。

  • 普通廣搜:每次往四個方向搜一個格子。
  • 這道題:每次往四個方向搜到不能搜為止。

其實很像最小拐彎問題吧。
還有,這道題的 v i s vis 陣列也會有一個小變化。當我們搜到一個點 (

x , y ) (x,y) v i s [
x ] [ y ] = t r u e vis[x][y]=true
時,不要立刻 b r e a k break ,因為可能會遇到如下情況:
在這裡插入圖片描述
藍色的塊從綠色的塊轉移來, v i s vis 已經被標記。
在這裡插入圖片描述
我們現在要從紅色點往右搜,那麼
在這裡插入圖片描述
當我們搜到 ( 3 , 3 ) (3,3) 時,如果直接退出,不繼續往後搜,那麼就會導致 ( 3 , 4 ) (3,4) 的本來應該搜到的格子無法搜到。
所以就應該直接跳過已被標記的格子,直接跳到下一個
在這裡插入圖片描述
注意終點 ( n , m ) (n,m) 也有可能是 S S 。但是這種情況還是算可以到達的。記得先將終點的 S S 去掉。


程式碼:

#include <cstdio>
#include <queue>
#include <ctime>
#include <cstring>
#include <iostream>
#define N 510
using namespace std;

const int dx[]={0,1,-1,0,0};
const int dy[]={0,0,0,1,-1};
const char way[]={' ','D','U','R','L'};  //四個方向
int n,m;
char c[N][N];
bool vis[N][N];

void bfs()
{
	queue<int> x;
	queue<int> y;
	queue<int> dis;
	vis[1][1]=1;
	x.push(1);
	y.push(1);
	dis.push(-1);
	while (x.size())
	{
		if (c[x.front()][y.front()]!='S')
		 for (int i=1;i<=4;i++)
		 {
			if (c[x.front()][y.front()]==way[i]) continue;
			int k=0;
			while (1)
			{
				k++;
				int xx=x.front()+k*dx[i];
				int yy=y.front()+k*dy[i];
				if (xx<1||yy<1||xx>n||yy>m) break;
				if (c[xx][yy]=='S') break;
				if (c[xx-dx[i]][yy-dy[i]]==way[i]) break;
				if (vis[xx][yy]) continue;
				vis[xx][yy]=1;
				x.push(xx);
				y.push(yy);
				dis.push(dis.front()+1);
				if (xx==n&&yy==m)
				{ 
					printf("%d",dis.front()+1);
					return;
				}
			}
		 }
		x.pop();
		y.pop();
		dis.pop();
	}
	printf("No Solution");
	return;
}		

int main()
{
	cin>>n>>m;
	if (n==1&&m==1) 
	{
		printf("0");
		return 0;
	}
	for (int i=1;i<=n;i++)
	 cin>>c[i]+1;
	c[n][m]=' ';
	bfs();
	return 0;
}