zoj_2412 Farm Irrigation

题目链接zoj 2412

题目翻译

有11种正方形,每种正方形里面对应一种形状的水管,不同的的正方形用A到K表示,给一个由不同正方形聚成的矩阵,问至少需要多少个水源可以使矩形中所有的地方都可以被灌溉,如果两个相邻的正方形的水管正好对口,那么这两个正方形可以共用一个水源。

分析

又是一道基础的深搜题,逐渐找到点门路啦。

第一步:

声明四个二维数组,第一个用于存放输入的正方形矩阵,第二个存放A-K代表的水管类型,第三个存放方向,第四个存放标志位。

还有一个变量mark,用来说明该正方形是否需要一个新的水源。

第二步:

定义dfs函数,参数是当前方格的横纵坐标。

首先说明返回条件,越界或已被访问都要返回;然后将flag数组对应的元素和mark全部置为true,表示已经被访问过,且需要一个新的水源;最后说明执行递归的条件,如果当前方格与它的上/下/左/右任意一个方格的水管对口,就继续访问与它对口的这个方格,直到找到一个水管不对口的方格,,返回函数,水源数加一。

第三步:

定义main函数,主要是输入输出操作。

输入的时候数组的下标从1开始,这样在深搜下一个方向时,就不会因为数组越界出错了;

用memset将标志位全部置为false;

切记:每遍历数组的一行后,要用getchar()读入回车,否则下一行的第一个元素就是回车。


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

//行代表字母A-K,列代表水管方向,第一三列是右左,第二四列是下上
int grid[11][4] = {{0,0,1,1},{1,0,0,1},{0,1,1,0},{1,1,0,0},{0,1,0,1},
    {1,0,1,0},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,0,1},{1,1,1,1}};

int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
bool flag[55][55];//标记当前格是否被访问过
int s[55][55];//存放格子的水管类型
bool mark=false;
int n,m;

void dfs(int i,int j)
{
    if(i<=0||i>m||j<=0||j>n) return;
    if(flag[i][j]) return;
    mark=true;
    flag[i][j]=true;
    for(int k=0; k<4; k++)
        if(grid[s[i][j]][k] && grid[s[i+dir[k][0]][j+dir[k][1]]][(k+2)%4])
            dfs(i+dir[k][0],j+dir[k][1]);
    return;
}

int main()
{
    while(scanf("%d%d",&m,&n))
    {
        if(m+n<0) break;
        char ch;
        getchar();
        int cnt=0;
        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%c",&ch);
                s[i][j]=ch-'A';//A的ASCII码为65
            }
            getchar();//读入当前行的回车
        }
        memset(flag,false,sizeof(flag));
        for(int i=1; i<=m; i++)
            for(int j=1; j<=n; j++)
            {
                mark=false;
                if(!flag[i][j]) dfs(i,j);
                if(mark) cnt++;
            }
        printf("%d\n",cnt);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值