DFS及其优化
DFS及其优化
[优化剪枝] 1.优化搜索顺序 先搜索节点少的分支,如果搜进来一个大分支而答案不在此分支就会浪费大量时间。 2.可行性剪枝 如果当前分支不可行就退出剪枝。 3.最优性剪枝 如果当前搜索到的答案已经比搜过的答案差了,就退出当前剪枝。 即如果此分支确定不是最优解(差于已有解)就 return。 4.记忆化搜索(=排除等效冗余) 记录之前搜过 Data ,避免重复搜。 例题: 1.accoders的【一本通基础搜索与回溯】红与黑1862 思路:一个简单的dfs,但是n和m的输入是反的!!! code: #include<bits/stdc++.h> using namespace std; char a[50][50]; int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1},vis[50][50]; int n,m,sum=0; int dfs(int x,int y){ for(int i=1;i<=4;i++){ int xx=x+dx[i],yy=y+dy[i]; if(xx>0&&xx<=m&&yy>0&&yy<=n&&a[xx][yy]=='.'&&!vis[xx][yy]){ sum++; vis[xx][yy]=1; dfs(xx,yy); } } return sum; } int main(){ while(1){ cin>>n>>m; if(n==0&&m==0){ return 0; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ cin>>a[i][j]; } } int sx,sy; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ if(a[i][j]=='@'){ sx=i,sy=j; } } } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ vis[i][j]=0; } } sum=1; vis[sx][sy]=1; cout<<dfs(sx,sy)<<"\n"; } return 0; } 2. accoders【一本通基础搜索与回溯】马走日1865 思路: 边界是0~n-1和0~m-1!!! code: #include<bits/stdc++.h> using namespace std; int n,m,x,y,vis[10][10]; int dx[10]={0,2,2,1,-1,-2,-2,1,-1},dy[10]={0,1,-1,2,2,1,-1,-2,-2}; int ans=0,tot; void dfs(int nx,int ny,int now){ if(tot==now){ ans++; return; } for(int i=1;i<=8;i++){ int xx=nx+dx[i],yy=ny+dy[i]; if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]){ vis[xx][yy]=1; dfs(xx,yy,now+1); vis[xx][yy]=0; } } } int main(){ int T; cin>>T; while(T--){ ans=0; cin>>n>>m>>x>>y; // memset(vis,0,sizeof(vis)); tot=n*m; vis[x][y]=1; ans=0; dfs(x,y,1); vis[x][y]=0; cout<<ans<<"\n"; } return 0; } 3. accoders 【算法进阶 搜索深度优先搜索】小猫爬山 luogu P10483 小猫爬山 思路: 从大到小排,能塞就塞,不能就新开。 code: #include<bits/stdc++.h> using namespace std; int a[101],sum[101]; int n,w; int cmp(int x,int y){ return x>y; } int ans; void dfs(int u,int k){ if(k>=ans)return; if(u==n){ ans=k; return ; } for(int i=0;i<k;i++){ if(sum[i]+a[u]<=w){ sum[i]+=a[u]; dfs(u+1,k); sum[i]-=a[u]; } } sum[k]=a[u]; dfs(u+1,k+1); sum[k]=0; } int main(){ cin>>n>>w; for(int i=0;i<n;i++){ cin>>a[i]; } sort(a,a+n,cmp); ans=n; dfs(0,0); cout<<ans; return 0; } 4. luogu P1784 数独 思路: 一个判断行,列,小方格内有没有重复数字的dfs code: #include<bits/stdc++.h> using namespace std; int h[11][11],l[11][11],g[11][11],sd[11][11]; void go_out(){ for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ cout<<sd[i][j]<<" "; } cout<<"\n"; } exit(0); } void dfs(int x,int y){ if(sd[x][y]!=0){ if(x==9&&y==9){ go_out(); }else if(y==9){ dfs(x+1,1); }else{ dfs(x,y+1); } }else{ for(int i=1;i<=9;i++){ if(!h[x][i]&&!l[y][i]&&!g[(x-1)/3*3+(y-1)/3+1][i]){ sd[x][y]=i; h[x][i]=l[y][i]=g[(x-1)/3*3+(y-1)/3+1][i]=1; if(x==9&&y==9){ go_out(); }else if(y==9){ dfs(x+1,1); }else{ dfs(x,y+1); } h[x][i]=l[y][i]=g[(x-1)/3*3+(y-1)/3+1][i]=0; sd[x][y]=0; } } } } int main(){ for(int i=1;i<=9;i++){ for(int j=1;j<=9;j++){ int t; cin>>t; if(t!=0){ h[i][t]=l[j][t]=g[(i-1)/3*3+(j-1)/3+1][t]=1; } sd[i][j]=t; } } dfs(1,1); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库