zoukankan      html  css  js  c++  java
  • DFS 深度优先搜索例题

      约翰的农场被暴风雨给淹没了,损失很大,他的保险公司将支付给他,但是支付金额取决于被淹没的最大面积。这个农场是一个边长分别为n、m的矩形,包含nm个空间,每个空间要么是干的,要么是被淹没的,一共有k个空间被淹没。求最大的淹没面积。

    题目分析:首先建立坐标,标记被淹没的空间,然后从左上角搜索被淹没的空间,并取消标记,再以此为中心向四周搜索是否有被淹没的空间,有的话继续计数并取消标记,以此类推,找出所有被淹没的空间,最后排序,找到被淹没最大的面积。

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    int a[110][110];
    int num[110];
    int ans,n,m;
    void dfs(int x,int y)  //深度优先搜索
    {
      if(a[x][y]==1||x<1||x>n||y<1||y>m)  //判断是否越界,是否是被淹没的
          return ;
       num[ans]++;  //计数
       a[x][y]=1;
       dfs(x-1,y);
       dfs(x+1,y);
       dfs(x,y+1);
       dfs(x,y-1);
    }
    int main()
    {
       int i,j,k,x,y;
       while(~scanf("%d%d%d",&n,&m,&k))
       {
          ans=-1;
          memset(num,0,sizeof(num));  //初始化
          for(i=1;i<=n;i++)  //建立坐标
             for(j=1;j<=m;j++)
                a[i][j]=1;
          while(k--)
          {
             scanf("%d%d",&x,&y);  //标记被淹没的
              a[x][y]=0;
          }
          for(i=1;i<=n;i++)
             for(j=1;j<=m;j++)
             {
              if(a[i][j]==0)  //搜索被淹没的
              {
                 ans++;
                 dfs(i,j);
              }
         }
        sort(num,num+ans+1);  //快排
        printf("%d ",num[ans]);
      }
      return 0;
    }

    题目大意:春天来了,汤姆有一块包含n*m个方块良田,他有一个耕种机器(位于左上角),但是其中有一些方块田地有大石块,机器不能通过,然而他想把没有石块的全部良田耕种,可能吗?

    题目分析:首先利用字符串建立地图,找出所以有石块的田地并计数,然后从左上角搜索没有石块的良田并标记计数,然后判断下一块田地是否可以耕种,以此类推,直到不能再耕种,判断所记的数目是否等于所有田地的总数目

    • #include <stdio.h>  
    • #include <string.h>  
    • char str[10][10];  
    • int n,m,sum;  
    • bool flag;  
    • void dfs(int x,int y)       //深度优先搜索   
    • {  
    • if(x<0||x>n-1||y<0||y>m-1||str[x][y]=='S')      //排除不符合条件的   
    • return ;  
    •     sum++;  
    •     str[x][y]='S';      //标记   
    • if(sum==n*m)        //判断是否可以全部耕种   
    •     {  

            flag=true;  

    • return ;  
    •     }  
    •     dfs(x-1,y);  
    •     dfs(x+1,y);  
    •     dfs(x,y-1);  
    •     dfs(x,y+1);  
    •     sum--;  
    •     str[x][y]='.';  
    • }  
    • int main()  
    • {  
    • int i,j;  
    • while(scanf("%d%d",&n,&m),n||m)  
    •     {  
    •         sum=0;  
    •         flag=false;  
    • for(i=0;i<n;i++)     //利用字符串输入,省时   
    •             scanf("%s",&str[i]);  
    • for(i=0;i<n;i++)     //找出有石块的田地   
    • for(j=0;j<m;j++)  
    • if(str[i][j]=='S')  
    •                     sum++;  
    •         dfs(0,0);  
    • if(flag)  
    •             puts("YES");  
    • else  
    •             puts("NO");  
    •     }  
    • return 0;  

    }  

    从 k数组中选择 6 个元素的组合,写出所有的可能情况。

    题目分析:其实这个题目有个不好处理的就是最后一个案例不能有换行。把案例看成以文件读入读出,第一个输出不换行,第二个输入再换行。递归实现从 n 个元素中选择 m  个元素,常规法.从头到尾一个一个的找(深度优先搜寻),并递归替换。

    #include <stdio.h>  

    • #include <string.h>  
    • int a[50],b[7];  
    • int n;  
    • void dfs(int top,int sum)       //深度优先搜索   
    • {  
    •     if(sum>=6)       //满足条件输出   
    •     {  
    •         for(int i=0;i<6;i++)  
    •         {  
    •             if(i)  
    •                 printf(" ");  
    •             printf("%d",b[i]);  
    •         }  
    •         puts("");  
    •         return ;  
    •     }  
    •     for(int i=top;i<n;i++)       //不满足条件继续搜索   
    •     {  
    •         b[sum]=a[i];  
    •         dfs(i+1,sum+1);       
    •     }  
    •     return ;  
    • }  
    •   
    • int main()  
    • {  
    •     int j;  
    •     while(scanf("%d",&n),n)  
    •     {  
    •         if(j++)     //输出空行   
    •             puts("");  
    •         for(int i=0;i<n;i++)  
    •             scanf("%d",&a[i]);  
    •         dfs(0,0);  
    •     }  
    •     return 0;  
    • }  

    变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个统一规律:如果咒语是以a开头b结尾的一个单词,那么它的作用就恰好是使A物体变成B物体。现在将他所会的所有咒语都列成了一个表,他想让你帮忙计算一下他是否能完成老师的作业,将一个B(ball)变成一个M(Mouse)。

    题目分析:首先搜索首字母为“B”的单词,然后标记已搜索过,再搜索首字母为上一个单词的尾字母并标记,直到找到尾字母为“M”的单词,输出“Yes.”,如果搜索不到此单词输出“No.”。

    #include <stdio.h>  

    • #include <string.h>  
    • #include <algorithm>  
    • using namespace std;  
    •   
    • int vis[1000];  
    • int flag,k;  
    •   
    • struct node     //构建结构体,分别记录单词的首字母和尾字母   
    • {  
    •     int start;  
    •     int end;  
    • }word[1000];  
    •   
    • void dfs(char c)        //深度优先搜索   
    • {  
    •     char temp;  
    •     if(c=='m')      //判断是否找到字母“M”   
    •     {  
    •         flag=1;  
    •         return ;  
    •     }  
    •     for(int i=1;i<k;i++)  
    •         if(vis[i]==0&&word[i].start==c)     //单词没有被搜索过,并且首字母为上一个字母的尾字母   
    •         {  
    •             temp=c;  
    •             c=word[i].end;  
    •             vis[i]=1;       //对于搜索过的单词进行标记   
    •             dfs(c);  
    •             c=temp;  
    •         }  
    • }  
    •   
    • int main()  
    • {  
    •     int i,len;  
    •     char a[100];  
    •     k=1;        //初始化   
    •     while(gets(a)!=NULL)  
    •     {  
    •         if(strcmp(a,"0")==0)        //判断是否输入结束   
    •         {  
    •             flag=0;  
    •             dfs('b');       //搜索首字母为“b” 的单词   
    •             if(flag)  
    •                 puts("Yes.");  
    •             else  
    •                 puts("No.");  
    •             k=1;        //初始化   
    •         }  
    •         else  
    •         {  
    •             len=strlen(a);  
    •             word[k].start=a[0];  
    •             word[k].end=a[len-1];  
    •             vis[k]=0;  
    •             k++;  
    •         }  
    •     }  
    •     return 0;  
    • }  

    在有若干个城墙的n*n的城市里建立大炮,大炮威力很大,除了城墙都能打透,所以两门大炮不能在同一行,或同一列,除非中间有城墙隔着,问最多能建立多少个大炮。

    题目分析:从左上角开始搜索,判断是否能安排大炮(此位置的上方和左方不能有大炮,除非有城墙隔着),能安排大炮就标记并统计大炮数目,以此类推,直到所有地方不能安排大炮,输出最多安排大炮的数量。

    #include <stdio.h>  

    • #include <string.h>  
    • #include <algorithm>  
    • using namespace std;  
    • char str[5][5];  
    • int t,sum;  
    • bool vis(int x,int y)       //判断此位置的上方,左方是否有大炮或者城墙   
    • {  
    •     int i;  
    •     for(i=x-1;i>=0;i--)  
    •     {  
    •         if(str[i][y]=='0')  
    •             return false;  
    •         if(str[i][y]=='X')  
    •             break;  
    •     }  
    •     for(i=y-1;i>=0;i--)  
    •     {  
    •         if(str[x][i]=='0')  
    •             return false;  
    •         if(str[x][i]=='X')  
    •             break;  
    •     }  
    •     return true;  
    • }  
    • void dfs(int x,int y)  
    • {  
    •     int a,b;  
    •     if(x==t*t)      //是否已经全部搜索完毕   
    •     {  
    •         if(y>sum)        //sum为最多大炮数量   
    •         {  
    •             sum=y;  
    •             return ;  
    •         }  
    •     }  
    •     else  
    •     {  
    •         a=x/t;      //a为行数   
    •         b=x%t;      //b为列数   
    •         if(str[a][b]=='.'&&vis(a,b))        //判断此位置是否为空地   
    •         {  
    •             str[a][b]='0';      //标记已安排大炮   
    •             dfs(x+1,y+1);       //搜索数目和安排的大炮数目分别+1   
    •             str[a][b]='.';  
    •         }  
    •         dfs(x+1,y);     //搜索数目+1   
    •     }  
    • }  
    • int main()  
    • {  
    •     int i;  
    •     while(scanf("%d",&t)&&t)  
    •     {  
    •         sum=0;  
    •         for(i=0;i<t;i++)     //输入地图   
    •             scanf("%s",str[i]);  
    •         dfs(0,0);       //从左上角开始搜索   
    •         printf("%d ",sum);  
    •     }  
    •     return 0;  
    • }  

    用自己已有的卡片等价交换自己想要的卡片,一共有多少种交换方法。

    题目分析:首先将自己所拥有的卡片的价值和数量输入并保存在结构体中,然后进行卡片交换,记录一共有多少种符合等价交换的交换方式

    #include <stdio.h>  

    • #include <string.h>  
    • #include <algorithm>  
    • using namespace std;  
    • int sum,m;  
    • struct note     //建立结构体   
    • {  
    •     int value;  
    •     int num;  
    • }a[11];  
    • void dfs(int x,int y,int z)     //深度优先搜索   
    • {  
    •     if(y==z)        //符合条件   
    •     {  
    •         sum++;  
    •         return ;  
    •     }  
    •     if(y>z||x==m)        //价值超出,不符合条件   
    •         return ;  
    •     for(int j=0;j<=a[x].num;j++)  
    •         dfs(x+1,y+j*a[x].value,z);      //递归   
    • }  
    • int main()  
    • {  
    •     int n,i,b=-1;  
    •     while(~scanf("%d%d",&n,&m))  
    •     {  
    •         for(i=0;i<m;i++)  
    •             scanf("%d%d",&a[i].value,&a[i].num);  
    •         b++;  
    •         if(b)  
    •             puts("");  
    •         sum=0;  
    •         dfs(0,0,n);  
    •         printf("%d ",sum);  
    •     }  
    •     return 0;  
    • }  

    设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,...,wn。问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S。如果有满足条件的选择,则此背包有解,否则此背包问题无解。第一行为物品重量S(整数); 第二行为物品数量n,  第三行为n件物品的重量的序列。

    有解就输出”yes!“,没有解就输出”no!“。

    #include <iostream>

    #include <cstring>

    using namespace std;

    int wsum = 0;//背包里总重量

    int flag = 0;//旗帜法

    int book[100];//标记法

    void DFS(int S, int m, int w[])//深搜算法

    {  

      if (wsum == S)  

      { 

         flag = 1;   

         return;

       }  

      else

      {   

        for (int i = 0; i < m; i++)   

        {   

           if (book[i] == 0)    

          {     

            wsum += w[i];     

            book[i] = 1;     

            DFS(S, m, w);     

            wsum -= w[i];     

            book[i] = 0;    

           }   

        }  

      }  

      return;

    }

    int main()

    {  

      memset(book, 0, sizeof(book));  

      int w[100];  

      int S, m;  

      cin >> S >> m;  

      for (int i = 0; i < m; i++)   

        cin >> w[i];  

      DFS(S, m, w);  

      if (flag == 1)   

        cout << "yes!";  

      else  

         cout << "no!";

       return 0;

    }

     

     

  • 相关阅读:
    WSP部署错误—SharePoint管理框架中的对象“SPSolutionLanguagePack Name=0”依赖其他不存在的对象
    Elevate Permissions To Modify User Profile
    Error with Stsadm CommandObject reference not set to an instance of an object
    ASP.NET MVC3添加Controller时没有Scaffolding options
    测试使用Windows Live Writer写日志
    配置TFS 2010出现错误—SQL Server 登录的安全标识符(SID)与某个指定的域或工作组帐户冲突
    使用ADO.NET DbContext Generator出现错误—Unable to locate file
    CSS
    HTML DIV标签
    数据库
  • 原文地址:https://www.cnblogs.com/huyao/p/6670120.html
Copyright © 2011-2022 走看看