DFS的核心就是从一种状态出发,转向任意的一个可行状态,直到达到结束条件为止。(个人理解)
下面全是洛谷题,毕竟能找到测试点数据的OJ我就找到这一个....在其他OJ上直接各种玄学问题...
P1596 [USACO10OCT] 湖计数Lake Counting
DFS入门题,求连通块的。
1 #include2 #include 3 using namespace std; 4 int dx[8]={-1,-1,-1, 0, 0, 1,1,1};//方向 5 int dy[8]={-1, 0, 1,-1, 1,-1,0,1}; 6 char mapp[110][110];//地图 7 int n,m; 8 9 void dfs (int x,int y) 10 { 11 int nx,ny; 12 mapp[x][y]='.';//每进入一个状态就把这个点去掉,避免重复进入DFS 13 for (int i=0;i<8;i++) 14 { 15 nx=x+dx[i]; 16 ny=y+dy[i]; 17 if (nx<0||nx>=n||ny<0||ny>=m) 18 continue; 19 if (mapp[nx][ny]=='W')//如果‘.’也能走的话,那整块图都可以走了... 20 dfs(nx,ny);//进入到下一个状态 21 } 22 return ; 23 } 24 25 int main() 26 { 27 scanf("%d %d",&n,&m); 28 int fin=0; 29 for (int i=0;i ) 30 scanf("%s",mapp[i]);//这样读一行 31 for (int i=0;i ) 32 { 33 for (int j=0;j ) 34 { 35 if (mapp[i][j]=='W') 36 { 37 dfs(i,j);//每次DFS一遍后,整块湖泊就算填平了 38 fin++; 39 } 40 } 41 } 42 printf("%d\n",fin); 43 return 0; 44 }
P1506 拯救oibh总部
可以用上面一道题的思路代,方向从八向变为四向
要模拟一下海浪冲到总部上,这次读入地图的时候我给它先套了一圈“海浪”,从海浪中的一点出发,dfs一遍,如果是没有被保护的基地就被淹了,剩下的遍历一遍就行
1 #include2 #include 3 using namespace std; 4 int n,m; 5 char mm[600][600]; 6 int dx[4]={0,0,1,-1}; 7 int dy[4]={1,-1,0,0}; 8 void dfs(int x,int y) 9 { 10 mm[x][y]='*'; 11 int nx,ny; 12 for (int i=0;i<4;i++) 13 { 14 nx=x+dx[i]; 15 ny=y+dy[i]; 16 if (nx>=0&&nx<=n+1&&ny>=0&&ny<=m+1&&mm[nx][ny]=='0') 17 dfs(nx,ny); 18 } 19 return ; 20 } 21 int main() 22 { 23 int fin=0; 24 for (int i=0;i<550;i++) 25 for (int j=0;j<550;j++) 26 mm[i][j]='0'; 27 cin>>n>>m; 28 for (int i=1;i<=n;i++) 29 for (int j=1;j<=m;j++) 30 cin>>mm[i][j]; 31 dfs(0,0); 32 for (int i=1;i<=n;i++) 33 for (int j=1;j<=m;j++) 34 if (mm[i][j]=='0') 35 fin++; 36 cout<<fin; 37 return 0; 38 }
P1076 全排列问题
上面两道不需要管回溯,所以很简单
全排列最大的问题就是有一个回溯的过程
记一下这个题的运行过程,假如输一个3
1没被用过,选1,填1,进dfs(2)
找到2没被用过,选2填2,进dfs(3)
找到3没被用过,选3填3,进dfs(4)
满足输出条件,输出
此时,回到了dfs(3)的时候,现在把num[3]化为0
回到了dfs(2)的时候,把num[2]化为0,现在还在for循环中,转到num[3]=0,于是pai[2]=3
类推,输出完1 3 2之后,回到dfs(1),for循环到2,从2开头搜....
反正我真的想了很久没想通回溯,自己写一下就好了
#include#include using namespace std; int n; int num[10]={0}; int pai[10]={0}; void dfs(int x) { if (x==n+1)//就是n个格子都被填满的时候,这时候需要输出 { for (int i=1;i<=n;i++) printf("%5d",pai[i]); printf("\n"); } else { for (int i=1;i<=n;i++) { if (num[i]==0)//找到了一个还没用的数字 { num[i]=1;//标记一下 pai[x]=i;//把数填进去 dfs(x+1);//搜下一个数 num[i]=0;//回溯 } } } } int main () { scanf("%d",&n); dfs(1);//从第一位开始搜起 return 0; }