zoukankan      html  css  js  c++  java
  • 咸鱼的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
    ",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("
    ");
        }
        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
  • 相关阅读:
    常见存储过程分页PK赛——简单测试分析常见存储过程分页速度
    简单的ASP.NET无刷新分页
    程序员45个好习惯
    手机应用兼职开发平台,欢迎有识之士参加...
    DotNetRemoting分布式安全部署(整理+原创)
    刚刚整理的截获SQL错误代码弹出提示信息类.
    485modbus通讯协议
    485通信
    ucoss在stm32上的移植
    使用OFFICE组件出问题环境配置
  • 原文地址:https://www.cnblogs.com/Salty-Fish/p/12253270.html
Copyright © 2011-2022 走看看