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;
}



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

相关文章推荐

UVA572 POJ1562 oil deposits(DFS求连通块问题)

 Description The GeoSurvComp geologic survey company is responsible for detecting undergroun...

UVa 572 - Oil Deposits (简单dfs)

Description GeoSurvComp地质调查公司负责探测地下石油储藏。 GeoSurvComp现在在一块矩形区域探测石油,并把这个大区域分成了很多小块。他们通过专业设备,来分析每个小块...

DFS入门精讲:油田(Oil Deposits UVA572)

传送门:https://vjudge.net/problem/UVA-572 具体原题看链接。 大意:输入一个m行n列字符矩阵,统计字符@组成多少个八连块(如果两个字符@所在格子横竖对角线方向相邻就...

uva 572 Oil Deposits(dfs)-解题记录

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu...

HDU 1241/UVa572 Oil Deposits(DFS&BFS)

Oil Deposits Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Tota...

POJ1111,Image Perimeters,典型dfs,跟八连块差不多

Image Perimeters Description Technicians in a pathology lab analyze digitized images of slides...

UVA - 572 - Oil Deposits (图的DFS!)

UVA - 572 Oil Deposits Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format:...

UVa 572 Oil Deposits(DFS)

题意 计算@连通块的数量 典型的dfs应用

UVA 572 搜索 初识BFS DFS

搜索

Uva572-poj-1562-hdoj--1241--oil Deposits-DFS

【科普】什么是BestCoder?如何参加? Oil Deposits Time Limit: 2000/1000 MS (Java/Others)    Memory Lim...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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