感觉这题的话还是BFS有优势吧,太深的话那DFS就炸了。不过实际上实现差不多。核心在于我们走全图,如果没走出去那就是绝对走不到。在自己所有衍生情况走完之后自己就结束了,我们可以很轻松的使用一个flag记录,并且把它当做关键的判断与边界条件
实现倒还是很简单很板子,很适合拿来当做练手熟悉DFS,这里就说几个我遇见的莫名其妙的错误:
1:老生常谈的段错误问题:我们一定要先检验index后检验内部。平常大多数时候我们会忽略掉index,只把他当作拿到元素的工具。不注重细节的结果就是像我一样段错误吃到爽。特别是在有很多的限制判断条件的情况下
if(tx >= 0 && tx < n && ty >= 0 && ty < m && themap[tx][ty] != 1 && !visited[tx][ty])//正确
if(!visited[tx][ty] && tx >= 0 && tx < n && ty >= 0 && ty < m && themap[tx][ty] != 1)//错误,段错误
2:这里要小心的是多组输入(他好歹还给你明说了,像NC15029这种不给你明说的那不看题解能WA到天荒地老),需要特别注意。为了方便,修补骑士有时候会设置一堆全局变量来配合DFS使用来减少代码量。但是这样有可能会造成一些莫名其妙的残留错误,上一次的数据可能会干扰到下一次。所以说与其为了那一点优化后面又来补漏洞。不如一开始就都全部传临时变量!
AC代码,果然大家还是要多写,不然就会和我一样没思路的没思路,有思路的全WA(池沼)
#include<bits/stdc++.h>
#define int long long
using namespace std;
//看样子这才是最板子的DFS?
int n,m;
int dirx[4] = {1,-1,0,0};
int diry[4] = {0,0,1,-1};
pair<int,int> thestart;
pair<int,int> theend;
bool flag = 0;
void dfs(int x,int y,vector<vector<int>> &themap,vector<vector<bool>> &visited)
{
//我们传引用哈,方便修改
visited[x][y] = 1;
if(flag == 1)
{
return;//随时随地都要剪枝是吧
}
if(x == theend.first && y == theend.second)
{
flag = 1;
return;
}
else
{
for(int r = 0;r < 4;r++)
{
int tx = x + dirx[r];
int ty = y + diry[r];
if(tx >= 0 && tx < n && ty >= 0 && ty < m && themap[tx][ty] != 1 && !visited[tx][ty])
{
dfs(tx,ty,themap,visited);
}
}
}
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
while(cin>>n>>m)//小心多组输入,这里基本上算是板子了
{
vector<vector<int>> themap(n,vector<int>(m,0));
vector<vector<bool>> visited(n,vector<bool>(m,0));
flag = 0;
for(int r = 0;r < n;r++)
{
for(int p = 0;p < m;p++)
{
char temp;
cin>>temp;
if(temp == 'S')
{
thestart.first = r;
thestart.second = p;
themap[r][p] = 0;
}
else if(temp == 'E')
{
theend.first = r;
theend.second = p;
themap[r][p] = 0;
}
else if(temp == '.')
{
themap[r][p]= 0;
}
else if(temp == '#')
{
themap[r][p] = 1;
}
}
}
dfs(thestart.first,thestart.second,themap,visited);
if(flag)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
return 0;
}