咸鱼的ACM之路:DFS水题集

DFS的核心就是从一种状态出发,转向任意的一个可行状态,直到达到结束条件为止。(个人理解)

下面全是洛谷题,毕竟能找到测试点数据的OJ我就找到这一个....在其他OJ上直接各种玄学问题...

P1596 [USACO10OCT] 湖计数Lake Counting

DFS入门题,求连通块的。

 1 #include<iostream>
 2 #include<algorithm>
 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<n;i++)
30         scanf("%s",mapp[i]);//这样读一行
31     for (int i=0;i<n;i++)
32     {
33         for (int j=0;j<m;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 }
View Code

P1506 拯救oibh总部

可以用上面一道题的思路代,方向从八向变为四向

要模拟一下海浪冲到总部上,这次读入地图的时候我给它先套了一圈“海浪”,从海浪中的一点出发,dfs一遍,如果是没有被保护的基地就被淹了,剩下的遍历一遍就行

 1 #include<iostream>
 2 #include<algorithm>
 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 }
View Code

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 <cstdio>
#include <iostream>
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;
}
View Code

 

posted @ 2020-02-02 19:11  Salty_Fish  阅读(175)  评论(0编辑  收藏  举报