dfs恢复现场以及回溯的理解
这种搜索树dfs就是一层一层来看,如果这一层的情况考虑结束了之后也就是都没有解了的时候,就开始回溯,回到上一层再判断,一定要记得回溯要恢复现场,先恢复现场再回溯,就是新的一层不能有任何标记
这一题不能走过重复的点,回溯的时候相当于换另一种选择的方式,原来标记过的点就需要把标记去掉
上一题单词接龙,每个单词不能使用超过两次,所以需要记录每个单词用过多少次,在回溯的时候,也就是这一层的单词都不可能匹配,这是新的一层,之前已经次数已经++了,这个时候要把之前加过的减掉(因为没有用过啊),然后退出这个新的一层,返回到其他的分支
单词接龙代码:
#include<iostream> using namespace std; const int N=100; string ch[N]; int g[N][N]; int used[N]; int n,res; void dfs(string dragon,int num)//龙和当前使用的字符串的编号 { res=max(res,(int)dragon.size()); used[num]++; for(int i=0;i<n;i++)//新的字符串 { if(g[num][i]&&used[i]<2)//能匹配上并且使用使用的次数少于两次 { dfs(dragon+ch[i].substr(g[num][i]),i); } }//如果全都不符合条件就退出循环,返回上一个分支,这个时候就是一个回溯的过程,把之前用过的字符次数-1 used[num]--;//回溯 } int main(){ cin>>n; for(int i=0;i<n;i++) cin>>ch[i]; char c; cin>>c; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { string a=ch[i],b=ch[j]; for(int k=1;k<min(a.size(),b.size());k++)//匹配的一个过程 if(a.substr(a.size()-k)==b.substr(0,k)) { g[i][j]=k;//重合了多少个字符 break; } } for(int i=0;i<n;i++) if(ch[i][0]==c) dfs(ch[i],i);//开始dfs cout<<res; return 0; } /* 每个都能两次,也是树的形式,每个单词伸出去一个分支 */
马走日的代码:
#include<iostream> using namespace std; int n,m,x,y,sum; const int N=1010; bool st[N][N]; int dx[8]={-1,-1,-2,-2,1,1,2,2}; int dy[8]={2,-2,1,-1,2,-2,1,-1}; void dfs(int x,int y,int u) { if(u==n*m) { sum++; return ; } st[x][y]=true; for(int i=0;i<8;i++) { int xx=x+dx[i],yy=y+dy[i]; if(xx>=0&&yy>=0&&xx<n&&yy<m&&!st[xx][yy]) { dfs(xx,yy,u+1); } }//这一层结束,所有的情况没了之后返回上一层 st[x][y]=false;//回溯 } int main(){ int T; cin>>T; while(T--) { sum=0; cin>>n>>m>>x>>y; dfs(x,y,1); cout<<sum<<endl; } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析