一、DFS(深度优先搜索)
1.八皇后问题&N皇后问题
题目:HDU-2553 网址:http://acm.hdu.edu.cn/showproblem.php?pid=2553
#include<iostream> using namespace std; int n,sum; int ans[12],sel[12]; int abs(int n)//求绝对值 { return n>0?n:-n; } void dfs(int h)//确定第i行的皇后的位置 { if(h>n)//成功,计数加一 { ++sum; return ; } int i,x,y;//(x,y)假定要放置的位置 x=h;//确定纵坐标,即行数 for(y=1;y<=n;++y)//确定横坐标 { //检查竖直方向,横着的方向就不用检测了,因为是一行行来的 for(i=1;i<x;++i) { if(y==sel[i]) break; } if(i<x)//失败 continue; //检查斜着的方向 for(i=1;i<x;++i) { if(abs(sel[i]-y)==x-i) break; } if(i<x)//失败 continue; sel[x]=y;//通过检测,存储当前位置的横坐标 dfs(h+1); } } int main() { for(n=1;n<=10;++n)//打表 { sum=0; dfs(1); ans[n]=sum; } while(cin>>n) { if(!n) break; cout<<ans[n]<<endl; } return 0; }
收获就是了解了打表,原来有时候打表可以提高效率防止超时。
2.题目:HDU-1716 网址:acm.hdu.edu.cn/showproblem.php?pid=1716
#include<bits/stdc++.h> using namespace std; //读题目可知四张卡片上的数字一定是0-9 int a[4],vis[4],ans[4]; set<int> s; void dfs(int step) { if(step==4) { int tmp=1000*ans[0]+100*ans[1]+10*ans[2]+ans[3]; s.insert(tmp); return ; } for(int i=0;i<4;++i) { if(step==0&&a[i]==0) continue; if(vis[i]) continue; vis[i]=1; ans[step]=a[i]; dfs(step+1); vis[i]=0; } } int main() { int pre,cnt=0; while(scanf("%d%d%d%d",&a[0],&a[1],&a[2],&a[3])) { //若输入四张卡片全是0则输入结束 if(!a[0]&&!a[1]&&!a[2]&&!a[3]) break; if(cnt) cout<<endl; cnt=1; s.clear(); sort(a,a+4); memset(vis,0,sizeof(vis)); dfs(0); for(set<int>::iterator it=s.begin();it!=s.end();it++) { int tmp=*it; if(it==s.begin()) { cout<<tmp; pre=tmp/1000; } else { if(tmp/1000==pre) cout<<" "<<tmp; else { cout<<endl<<tmp; pre=tmp/1000; } } } cout<<endl; } return 0; }
3.连通及连通块问题
题目:HDU-1312 网址:http://acm.hdu.edu.cn/showproblem.php?pid=1312
//这个题目可以这样理解:@代表起始点,.代表可以走的路,#代表墙 #include<bits/stdc++.h> using namespace std; char a[25][25]; int x;//列数 int y;//行数 int num; int dist[4][2]={{1,0},//向右 {-1,0},//向左 {0,1},//向上 {0,-1}};//向下 void DFS(int x0,int y0) { ++num; a[x0][y0]='#'; for(int i=0;i<4;++i) { int xx=x0+dist[i][0]; int yy=y0+dist[i][1]; if(xx>=0&&xx<y&&yy>=0&&yy<x&&a[xx][yy]=='.') DFS(xx,yy); } } int main() { int start_x;//开始的列数 int start_y;//开始的行数 while(scanf("%d%d",&x,&y)!=EOF) { getchar(); if(!x&&!y) break; for(int i=0;i<y;++i) { for(int j=0;j<x;++j) { scanf("%c",&a[i][j]); if(a[i][j]=='@') { start_x=i; start_y=j; } } getchar(); } num=0; DFS(start_x,start_y); cout<<num<<endl; } return 0; }
题目:HDU-1241 网址:http://acm.hdu.edu.cn/showproblem.php?pid=1241
#include<cmath> #include<cstring> #include<cstdio> #include<iostream> using namespace std; char a[101][101]; int x,y;//x代表行数,y代表列数 int dist[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int num=0;//油田的数量 void dfs(int x0,int y0) { if(a[x0][y0]!='@'||x0<0||y0<0||x0>=x||y0>=y) return ; a[x0][y0]='*'; dfs(x0-1, y0-1); dfs(x0-1, y0); dfs(x0-1, y0+1); dfs(x0, y0-1); dfs(x0, y0+1); dfs(x0+1, y0-1); dfs(x0+1, y0); dfs(x0+1, y0+1); } int main() { while(cin>>x>>y){ if(x==0) break; num=0; for(int i=0;i<x;++i) for(int j=0;j<y;++j) cin>>a[i][j]; for(int i=0;i<x;++i) for(int j=0;j<y;++j) { if(a[i][j]=='@') { ++num; dfs(i,j); } } cout<<num<<endl; } }
4.可转化成深搜的其他应用
题目:Codeforces-96B 网址:http://codeforces.com/problemset/problem/96/B
#include<cmath>#include<cstring>#include<cstdio>#include<iostream>using namespace std;char a[101][101];int x,y;//x代表行数,y代表列数int dist[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int num=0;//油田的数量void dfs(int x0,int y0){ if(a[x0][y0]!='@'||x0<0||y0<0||x0>=x||y0>=y) return ; a[x0][y0]='*'; dfs(x0-1, y0-1); dfs(x0-1, y0); dfs(x0-1, y0+1); dfs(x0, y0-1); dfs(x0, y0+1); dfs(x0+1, y0-1); dfs(x0+1, y0); dfs(x0+1, y0+1);}int main(){ while(cin>>x>>y){ if(x==0) break; num=0; for(int i=0;i<x;++i) for(int j=0;j<y;++j) cin>>a[i][j]; for(int i=0;i<x;++i) for(int j=0;j<y;++j) { if(a[i][j]=='@') { ++num; dfs(i,j); } } cout<<num<<endl; }}