今天接着完成那一系列的新手题目,但是发现好像分类有点问题,POJ1562和POJ1979。其中前一道是用深度优先遍历和广度优先遍历都可以,还可以使用并查集这个玩意儿,虽然我也不太清楚,但是貌似很厉害的样子。。。后者本质上就是一个递归,但是我认为如果实在要归类的话,应该是归于深度遍历的,不知道为什么大牛给出的类别是广度优先遍历的题目了,算了,这个也不是重点。

       1.   1562是给定一个M*N的矩阵块,由@和*组成,@表示油田,*表示空地,相邻的(水平或者垂直或者斜边)油田可以组成油田区域,求解矩形一共包含多少个这样的油田区域。

       我的思路:应该是图的遍历问题,首先想的是深度遍历,但是需要配合标记数组或者直接更改访问过的位置。不过一开始没有理解清楚题目的意思,光看Sample的结果就看了好半天,汗一个。。。。还好最后看懂了,知道怎么做了

 

       代码如下:

 
  
  1. #include<stdlib.h>   
  2. #include<stdio.h></span>   
  3. char map[101][101];   
  4. int m,n,i,j,sum;   
  5.    
  6. int DFS(int x,int y) {   
  7.     if(map[x][y] != '@' || x < 0 || y < 0 || x > m-1 || y > n-1)   
  8.         return 0;   
  9.     else {   
  10.         map[x][y] = '*';   
  11.         DFS(x-1,y-1);   
  12.         DFS(x-1,y);   
  13.         DFS(x-1,y+1);   
  14.         DFS(x,y-1);   
  15.         DFS(x,y+1);   
  16.         DFS(x+1,y-1);   
  17.         DFS(x+1,y);   
  18.         DFS(x+1,y+1);   
  19.     }   
  20. }   
  21.    
  22. int main() {   
  23.    
  24.    while(scanf("%d %d",&m,&n) != EOF) {   
  25.     if(m == 0)    
  26.         return 0;   
  27.        
  28.     for(i = 0; i < m; i++) {   
  29.         scanf("%s",map[i]);   
  30.     }   
  31.       
  32.     sum=0;   
  33.     for(i = 0; i < m; i++)   
  34.         for(j = 0; j < n; j++) {   
  35.             if(map[i][j] == '@') {   
  36.                 DFS(i,j);   
  37.                 sum++;   
  38.             }   
  39.                
  40.         }   
  41.     printf("%d\n",sum);   
  42.    }   
  43.    //system("pause");   
  44.    return 0;   
  45. }   

         题目总结:提交AC,但是发现网上使用BFS也可以解决,而且有使用并查集的,这个东西需要学习一下,明天在专门写一篇这个的研究吧,总之,题目的本质就是寻找图的连通分量的个数,至于怎么实现就各有千秋了,需要注意的是这个搜索是8个方向的。

        

        2.  1979 题目的意思还是给定字符矩阵,其中@代表一个人的起始位置,#代表红,.代表黑,人每次行走只能走黑而不能走红,问最多能走多远(其实位置记距离为1)?

        我的思路:因为前一个题的影响,对比之下,发现基本上是一样的,只不过这一次是先找到那个起始位置的坐标,然后向上下左右4个方向进行DFS

     

 
  
  1. #include<stdio.h>   
  2. #include<stdlib.h>   
  3.    
  4. char map[101][101];   
  5. int m,n,i,j,sum;   
  6.    
  7. int DFS(int x,int y) {   
  8.        
  9.     if(map[x][y] == '#' || x < 0 || y < 0 || x > m-1 || y > n-1)   
  10.         return 0;   
  11.     else {   
  12.         sum++;   
  13.         map[x][y] = '#';   
  14.         DFS(x-1,y);   
  15.         DFS(x,y-1);   
  16.         DFS(x,y+1);   
  17.         DFS(x+1,y);    
  18.     }   
  19. }   
  20.    
  21. int main() {   
  22.    
  23.    while(scanf("%d %d",&n,&m) != EOF) {   
  24.     if(n == 0)    
  25.         return 0;   
  26.        
  27.     for(i = 0; i < m; i++) {   
  28.         scanf("%s",map[i]);   
  29.     }   
  30.        
  31.     sum=0;   
  32.     for(i = 0; i < m; i++)   
  33.         for(j = 0; j < n; j++) {   
  34.             if(map[i][j] == '@') {   
  35.                 DFS(i,j);   
  36.             }    
  37.         }   
  38.            
  39.     printf("%d\n",sum);   
  40.    }   
  41.      
  42.    return 0;   
  43. }   

  

 

       题目总结:提交后AC,在网上搜到了解题报告,发现还是作为递归的典型问题来考虑比较好,基本上就是公式:

go(x,y)=1+go(x-1,y)+go(x+1,y)+go(x,y-1)+go(x,y+1)

具体的实现代码可以参见

http://www.cppblog.com/NARUTOACM/archive/2009/09/04/95324.h