没什么可说的,从起点开始,dfs四周,当到达#时return false,到达终点时return false。
dfs内算法流程应为:赋值st数组,遍历四周(要求在迷宫内且没被搜过),出循环后return false
#include
#include
#include
using namespace std;
const int N =110;
int n;
char g[N][N];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
bool st[N][N];
int xa,ya,xb,yb;
bool dfs(int x,int y)
{
if(g[x][y]=='#') return false;
if(x==xb&&y==yb) return true;
st[x][y]=true;
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0||b<0||a>=n||b>=n) continue;
if(st[a][b]) continue;
if(dfs(a,b)) return true;
}
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i>g[i];
memset(st,false,sizeof st);
cin>>xa>>ya>>xb>>yb;
if(dfs(xa,ya)) puts("YES");
else puts("NO");
}
return 0;
}
作者:yankai
链接:https://www.acwing.com/activity/content/code/content/4219882/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
从起点开始,dfs四周黑瓷砖。流程:每到一个新的点就res++,并且赋值st数组,然后dfs四周合法位置。遍历完整个搜索树时dfs结束。
#include
#include
#include
using namespace std;
const int N =25;
char g[N][N];
int n,m;
int xa,ya;
int ans;
bool st[N][N];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
void dfs(int x,int y)
{
ans++;
st[x][y]=true;
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0||b<0||a>=n||b>=m) continue;
if(st[a][b]) continue;
if(g[a][b]!='.') continue;
dfs(a,b);
}
}
int main()
{
while(cin>>m>>n,n||m)
{
for(int i=0;i>g[i][j];
if(g[i][j]=='@') xa=i,ya=j;
}
ans=0;
memset(st,false,sizeof st);
dfs(xa,ya);
cout<
求解:遍历整个棋盘的方案(dfs每次马跳的位置的选择)
分析:从起点dfs,搜索所有位置选择。流程:到一个新的地方,看已经遍历了几个格子,如果是n*m则ans++,并且return。赋值st数组,dfs四周所有没有到达过的合法位置。
略提一下:和前两题不同,本题dfs某个选择之后,要“恢复现场”,消除搜索这个分支带来的影响之后,再搜索下一个分支。
#include
#include
#include
using namespace std;
const int N =11;
bool st[N][N];
int n,m;
int xa,ya;
int ans;
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
void dfs(int x,int y,int cnt)
{
if(cnt==n*m)
{
ans++;
return ;
}
st[x][y]=true;
for(int i=0;i<8;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0||b<0||a>=n||b>=m) continue;
if(st[a][b]) continue;
dfs(a,b,cnt+1);
}
st[x][y]=false;//回溯 消除这条分支的影响
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m>>xa>>ya;
memset(st,0,sizeof st);
ans=0;
dfs(xa,ya,1);
cout<
直觉想法:从一个单词开始dfs,选择每一个可以接龙的单词接上(满足接龙接龙条件,并且使用次数不超过2次),接着dfs接上后的单词,直到没有龙可接。为了找出最长龙,设置全局变量ans,每dfs一个新单词时,把当前长度和ans比较即可。
完善:预处理可以接龙的单词和重合部分的长度。注意要回溯现场——used数组
#include
#include
#include
using namespace std;
const int N =25;
string word[N];
int g[N][N];
int used[N];
int n;
int ans;
void dfs(string dragon,int last)
{
ans=max(ans,(int)dragon.size());
used[last]++;
for(int i=0;i>n;
for(int i=0;i>word[i];
char start;
cin>>start;
for(int i=0;i
直觉想法:在组中选择一个数,在剩下的数中继续选择,在遍历的过程中:如果某个数和组内所有数互质的话就加入这个组,然后把这个组的情况深搜下去,如果不互质就跳过。。遍历继续:如果继续遇到其他和这个数互质的,同上,就加入组内然后深搜这个情况。如果遍历结束之后都没有遇到和组内所有数互质的,就开新一个组。
细化:可以实时记录当前已经将多少个数加入组内、开了多少个组。当所有数都加入组内时深搜回溯,记录ans。当当前开的组数大于ans时,直接剪枝。
然后发现需要一个数组记录那些数已经选择过。然后知道我们在回溯时需要“恢复现场”。
本题是组合型枚举,组内的元素顺序并不影响结果。因此如果我们按下标从小到大的顺序枚举,那么我们将第i个数选入组中时,继续深搜时就不必要考虑前i个数,直接从第i+1个数搜起即可。
综上,dfs中需记录:开了几组、这个组内的元素个数(为了方便遍历组内以有元素来判断是否能够将某个数放入组中)、已经搜索过的元素个数、该次dfs可以从哪个数开始搜起。
#include
#include
#include
using namespace std;
const int N =15;
//递归组合型枚举
int group[N][N];
int n;
bool st[N];
int p[N];
int ans=N;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
bool check(int group[],int gc,int i )
{
for(int j=0;j1)
return false;
return true;
}
//第几组 组内元素个数 已经搜到的元素个数 组内可以从哪个点开始搜
void dfs(int g,int gc,int tc,int start)
{
if(g>=ans) return ;
if(tc==n) ans=g;
bool flag=true;
for(int i=start;i>n;
for(int i=0;i>p[i];
dfs(1,0,0,0);
cout<