uva572--dfs求八连块

原创 2016年05月30日 15:32:17

题意:

输入一个 m 行 n 列的字符矩阵,统计字符 @ 能组成多少八连块,如果两个字符 @ 所在的格子相邻(横竖或者对角线的方向),就

说他们组成了一个八连块,问图中一共有多少个八连块。



Sample Input:

1 1

*

3 5

*@*@*

 **@**

*@*@*

1 8

@@****@*

5 5

****@

*@@*@

*@**@

@@@*@

@@**@

0 0

Sample Output:

0

1

2

2



分析:

图和二叉树一样,也有自己的dfs 和 bfs遍历,一般dfs用来求连通块问题,bfs用来找最短路问题,这个题目就是一个典型的dfs求八

连块的问题,可以从每个 @ 字符出发,递归遍历他周围八个方向的字符,看是否是 @ 格子,如果是就标记一下,证明该格子遍历

过,这样在以后的访问的时候,就能知道他是否被访问过,从而避免同一个格子被访问多次。下面的代码用一个二重循环来寻找八

连块,当然也可以用常量数组或者8条dfs遍历,在这里说一下,图的dfs遍历用递归实现,bfs遍历则是用队列(或者数组)实现,

类似的还有求二连块,四连块,等等,都可以用dfs遍历来实现,只需要改一下行走函数就可以。


下面上代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int n, m, maxz[105][105];
char str[105][105];


void dfs(int r,int c,int id)
{
    if(r < 0 || r >= n ||c < 0 ||c >= m)
        return;
    if(maxz[r][c] > 0 || str[r][c] != '@')
        return;
    maxz[r][c] = id;
    for(int dr = -1; dr <= 1; dr++)///两个方向同时移动可以往八个方向移动
        for(int dc = -1; dc <= 1; dc++)///而四连块则是单移动,仅一个for循环。
            if(dr != 0 || dc != 0)///这儿同时体现八连块,八方向
                dfs(r + dr, c + dc, id);
}

int main()
{
    while(scanf("%d%d",&n, &m) == 2&&n,m)
    {
        for(int i = 0; i < n; i++)
            cin >>str[i];
        memset(maxz, 0, sizeof(maxz));
        int cnt = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
            {
                if(str[i][j] == '@'&&maxz[i][j] == 0)
                {
                    dfs(i,j, ++cnt);
                    cnt = max(0, cnt);
                }
            }
        cout <<cnt<<endl;
    }
}


下面上四连块:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn=100+5;
int maze[maxn][maxn];///顶点访问状态
int R,C,K;///R行C列K个水块
int cnt,ans;///cnt是计算访问的格子数
///两个表示方向数组
int dr[]= {-1,1,0,0}; //上,下,左,右
int dc[]= {0,0,-1,1};

void dfs(int r,int c) ///r是行坐标,c是列坐标
{
    if(r<1||r>R ||c<1||c>C || maze[r][c]==0)
        return ;///超出范围或已经访问过的格子
    maze[r][c] = 0;///访问的格子
    cnt++;
    for(int d=0; d<4; d++)///四连块
        dfs(r+dr[d],c+dc[d]);
}

int main()
{
    while(scanf("%d%d%d",&R,&C,&K) == 3)
    {
        for(int i=1; i<=R; i++)///一定是从1开始
            for(int j=1; j<=C; j++)
                maze[i][j] = 0;///将初始的maze数组全部设置成false
        while(K--)///输入有水的格子坐标,设置成true
        {
            int i,j;
            scanf("%d%d",&i,&j);
            maze[i][j] = 1;
        }
        ans=0;
        for(int i=1; i<=R; i++)
            for(int j=1; j<=C; j++)
                if(maze[i][j]==1)
                {
                    cnt=0;
                    dfs(i,j);
                    ans=max(ans,cnt);///如果没有则输出0
                }
        printf("%d\n",ans);
    }
    return 0;
}



下面上二连块:

代码实现:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;


int map[650][650],p[650][650],x[650],y[650],vis[650];
int n,num,t,k;
char s[650][650];

bool Search(int i)///其实就是一个dfs
{
    int j;
    for(j=0; j<num; j++)
    {
        if(map[i][j] && !vis[j])
        {
            vis[j]=1;
            if(!y[j]||Search(y[j]))
            {
                y[j]=i;
                x[i]=j;
                return true;
            }
        }
    }
    return false;
}

int  match()
{
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    int ans=0;
    for(int i=0; i<num; i++)///寻找増广路
    {
        memset(vis,0,sizeof(vis));
        if(Search(i))///统计满足二连块的个数
            ans++;
    }
    return ans/2;
}

int main()
{
    k=1;
    cin>>t;
    while(t--)
    {
        memset(map,0,sizeof(map));
        cin>>n;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                cin>>s[i][j];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(s[i][j]=='#')
                    p[i][j]=num++;
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(s[i][j]=='#')
                {
                    if(j<n-1 && s[i][j+1]=='#')
                    {
                        map[p[i][j]][p[i][j+1]]=1;
                        map[p[i][j+1]][p[i][j]]=1;
                    }
                    if(j<n-1 && s[i+1][j]=='#')
                    {
                        map[p[i][j]][p[i+1][j]]=1;
                        map[p[i+1][j]][p[i][j]]=1;
                    }
                }
            }
        }
        int p=match();
        printf("Case %d: %d\n",k++,p);
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

算法竞赛入门第6章DFS算法解八连块问题java版

题目:找出n*n矩阵中的连块
  • miscocox
  • miscocox
  • 2014年05月12日 19:36
  • 706

八连块

Description 输入一个n*n(n最大为30)的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑格子有公共边或者有公共顶点,就说它们属于同一个八连块。 如下图...
  • u012634258
  • u012634258
  • 2013年11月21日 18:41
  • 583

C++ DFS求连通块

DFS求连通块
  • Binary_Heap
  • Binary_Heap
  • 2017年10月15日 18:09
  • 114

黑白图像—————— 八连块

八连块 【题目】:              输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑格子有        公共边或者公共顶点,就说它们属于同一个...
  • disparity_CJK
  • disparity_CJK
  • 2016年05月06日 15:08
  • 523

DFS求连通块(UVa 572)

图:图描述的是一些个体之间的关系与现行表和二叉树不同的是:这些个体之间既不*是前驱后继的关系,也不是祖先后代的层次关系,而是错综复杂的网状结构油田(Oil Deposits,UVa 572) 输入一...
  • Dextrad_ihacker
  • Dextrad_ihacker
  • 2015年11月26日 22:09
  • 567

八连块的个数

#include int n, count, a[31][31]; void dfs(int row, int col) { if((row n)||(col n)) return ; i...
  • u012620270
  • u012620270
  • 2013年11月16日 09:51
  • 1009

ACM油田问题

输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻,(横、竖或者对角线方向),就说他们属于一个八连块。例如:  *  *  *  * @  * @@ *@  ...
  • a1291985595
  • a1291985595
  • 2017年06月01日 14:07
  • 1000

uva_572_八连块_图论_DFS搜索

传送门:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_probl...
  • Allianzcortex
  • Allianzcortex
  • 2014年12月19日 08:52
  • 364

黑白图(八连块)

Problem 46: 八连块 Time Limit:1 Ms| Memory Limit:128 MB Difficulty:1 Description 输入一个n*...
  • u012689941
  • u012689941
  • 2013年11月17日 15:11
  • 515

算法竞赛入门经典(第2版)-刘汝佳-第六章解题源码(C++语言)(部分)

算法竞赛入门经典(第2版)-刘汝佳-第六章解题源码(C++语言)(部分)
  • LieQueov
  • LieQueov
  • 2017年08月12日 16:00
  • 947
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uva572--dfs求八连块
举报原因:
原因补充:

(最多只允许输入30个字)