思路:首先dfs求得所有联通块,再搜索的同时把每个联通块的坐标都保存下来,然后把每个联通块处理一下–首先得到某个联通块的最小横坐标和纵坐标,然后让每个坐标去减去这个横坐标和纵坐标。相当于使得所有联通块都位于左上角了,然后再对坐标按照x和y排序就可以保证相同的联通块的所有坐标都一致。

后来想了一下,其实可以不排序,因为我们都是两层循环枚举一个点来进行扩展的,如果两个联通块(岛屿)形状一致,那么每次开始搜索的起点都是同一个位置,并且搜索时保证方向一直是(上下左右或则其他),只要保证方向不变那么就不需要排序。


AC代码

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 50+5;
int n, m;
char a[maxn][maxn];
bool vis[maxn][maxn];
int numOfIsland, numOfArea, numOfShape;
map<int, int> area;

struct pos{
    int x, y;
    pos(int x, int y):x(x), y(y){
    }
    bool operator < (const pos& p) const {
        return x < p.x || (x == p.x && y < p.y);
    }
};

struct pic{
    vector<pos> arr;
    void push(pos p) {
        arr.push_back(p);
    }
    void deal() {
        int Area = arr.size();
        if(!area.count(Area)) {
            area[Area] = 1;
            numOfArea++;
        }
        int x = inf, y = inf;
        for(int i = 0; i < arr.size(); i++) {
            x = min(x, arr[i].x);
            y = min(y, arr[i].y);
        }
        for(int i = 0; i < arr.size(); i++) {
            arr[i].x -= x;
            arr[i].y -= y;
        }
        sort(arr.begin(), arr.end());
    }
}shape[maxn*maxn];

bool isSame(pic &a, pic &b) {
    vector<pos> &p1 = a.arr, &p2 = b.arr;
    if(p1.size() != p2.size()) {
        return false;
    }
    for(int i = 0; i < p1.size(); i++) {
        if(p1[i].x != p2[i].x || p1[i].y != p2[i].y) return false;
    }
    return true;
}

void init() {
    memset(vis, 0, sizeof(vis));
    numOfIsland = numOfArea = numOfShape = 0;
}

const int dx[] = {0,0,-1,1};
const int dy[] = {1,-1,0,0};

void dfs(int x, int y) {
    shape[numOfIsland].push(pos(x, y));
    vis[x][y] = 1;
    for(int i = 0; i < 4; i++) {
        int px = x + dx[i];
        int py = y + dy[i];
        if(px < 0 || px >= n || py < 0 || py >= m) continue;
        if(a[px][py] == '#' && !vis[px][py]) {
            vis[px][py] = 1;
            dfs(px, py);
        }
    }
}
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) {
        scanf("%s", a[i]);
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(!vis[i][j] && a[i][j] == '#') {
                dfs(i, j);
                shape[numOfIsland].deal();
                numOfIsland++;
            }
        }
    }
    for(int i = 0; i < numOfIsland; i++) {
        bool ok = 1;
        for(int j = 0; j < i; j++) {
            if(isSame(shape[j], shape[i])) {
                ok = 0;
                break;
            }
        }
        if(ok) numOfShape++;
    }
    printf("%d %d %d\n", numOfIsland, numOfArea, numOfShape);
    return 0;
}

如有不当之处欢迎指出!

hihoCoder1310 岛屿 (dfs)的更多相关文章

  1. hihocoder1310 岛屿

    hihocoder1310 岛屿 题意: 中文题意 思路: dfs,面积和数量都很好求,问题在岛屿形状上,感觉让人比较麻烦,用vector保存各个点,只要两个岛之间每个点距离一样就好了,这里的形状的定 ...

  2. hiho #1310 : 岛屿 (dfs,hash)

    题目2 : 岛屿 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给你一张某一海域卫星照片,你需要统计: 1. 照片中海岛的数目 2. 照片中面积不同的海岛数目 3. 照 ...

  3. 305. 岛屿数量 II

    题目: 假设你设计一个游戏,用一个 m 行 n 列的 2D 网格来存储你的游戏地图. 起始的时候,每个格子的地形都被默认标记为「水」.我们可以通过使用 addLand 进行操作,将位置 (row, c ...

  4. 每天一套题打卡|河南省第八届ACM/ICPC

    A 挑战密室 化学方程式求分子量 这题我懒得写了 可以用map<string,int>哈希表,表示每种分子的相对分子质量 之后,从头遍历到尾. 1.数字:连读直到不是数字 2.字母:连读直 ...

  5. nyoj 1237 最大岛屿(dfs)

    描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的战船黑珍珠1号要征服各个海岛的海盜,最后成为海盗王. 这是一个由海洋.岛屿和海盗组 ...

  6. 第八届河南省赛B.最大岛屿(dfs)

    B.最大岛屿 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 30  Solved: 18 [Submit][Status][Web Board] De ...

  7. 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)

    需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...

  8. 中矿新生赛 H 璐神看岛屿【BFS/DFS求联通块/连通块区域在边界则此连通块无效】

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 璐神现在有张n*m大小的地图,地图上标明了陆地(用 ...

  9. nyoj--1237--最大岛屿(dfs+数据处理)

    最大岛屿 时间限制:1000 ms  |  内存限制:65535 KB 难度: 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的战 ...

随机推荐

  1. Android开发之蓝牙Socket

    蓝牙Server端就是通过线程来注册一个具有名称和唯一识别的UUID号的BluetoothServerSocket, 然后就一直监听Client端(BluetoothSocket)的请求,并对这些请求 ...

  2. AM调制的FPGA实现

    一.说明: 功能:AM调制 平台:Vivado 2016.4 和 Matlab R2017a 二.原理: 1. AM调制原理 AM已调信号的时域表达式: 已调信号的频域表达式: 本质上AM调制就是频谱 ...

  3. JavaScript算法实现排序

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. Protobuf 从入门到实战

    简介 从第一次接触Protobuf到实际使用已经有半年多,刚开始可能被它的名字所唬住,其实就它是一种轻便高效的数据格式,平台无关.语言无关.可扩展,可用于通讯协议和数据存储等领域. 优点 平台无关,语 ...

  5. 【转】sed 高级用法

    首先,应该明白模式空间的定义.模式空间就是读入行所在的缓存,sed对文本行进行的处理都是在这个缓存中进行的.这对接下来的学习是有帮助的. 在正常情况下,sed将待处理的行读入模式空间,脚本中的命令就一 ...

  6. Ajax发送数据

  7. Hadoop-2.6.5安装

    简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构. 用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储. Hadoop实现了一个分布式文 ...

  8. java对象引用-要掌握的细节

    hello ,好久没来了. 今天我来和大家分享一下有关引用变量的注意事项,一是加深一下自己的理解,二是对这块不太理解的同学可以看看. 大神可飘过,有什么不对或不足的地方请多多指教,谢谢. 假设场景: ...

  9. VS工程中的Windows.h

    才发现这个Windows.h是有些奥秘的,不是随便引用就可以的. 1,C++工程,头文件引用要讲求一定顺序.如果cpp文件先引用a.h,再引用b.h,则后者自动包含a.h.这一点很重要. 2,Wind ...

  10. 浅析调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException

    废话不多说,直接进入正题:如何使用JSR303的validate,进行数据校验,失败后直接抛出异常加入流转信息中,并在form页面提示出来. 首先我们为了启用验证,需要向 项目中添加Bean验证的实现 ...