HDU 5925——Coconuts【离散化 + 求连通块】(2016 东北赛D题)
发布日期:2021-05-10 10:56:51 浏览次数:18 分类:精选文章

本文共 2475 字,大约阅读时间需要 8 分钟。

为了解决这个问题,我们需要计算给定网格中坏椰子的影响,将其分割成多个连通的好椰子块,并确定每个块的大小。由于网格可能非常大,我们采用离散化和图形处理的方法来高效地解决问题。

方法思路

  • 离散化处理:将网格按行和列分别离散化,生成较小的网格来处理,缩减问题规模。
  • 标记坏椰子:使用数组标记坏椰子的位置,以便在遍历时跳过这些点。
  • 连通块划分:在离散化后的网格中,使用DFS进行遍历,识别每个连通块,并计算其大小。
  • 结果输出:将所有连通块的大小排序后,输出结果。
  • 解决代码

    #include 
    #include
    #include
    #include
    #include
    #include
    using namespace std;typedef long long ll;int maxn = 205;int n, m, nc;int x[maxn], y[maxn];int xx[maxn], yy[maxn];int linex[maxn], liney[maxn];int nx, ny, cntx, cnty;map
    mapx, mapy;bool vis[maxn][maxn];ll ans[205 * 205];// 方向数组int dx[] = {1, -1, 0, 0};int dy[] = {0, 0, 1, -1};void dfs(int i, int j) { if (!judge(i, j)) return; vis[i][j] = true; ll sum = 0; for (int nx_i = i - 1; nx_i <= i; nx_i++) { for (int ny_i = j - 1; ny_i <= j; ny_i++) { queue
    q; q.push((i, j)); while (!q.empty()) { auto [a, b] = q.front(); q.pop(); sum += linex[mapx[x تح轻 + a]] * liney[mapy[y + b]}; for (int k = 0; k < 4; ++k) { int na = a + dx[k]; int nb = b + dy[k]; if (na >=1 && na <= cntx && nb >=1 && nb <= cnty && !vis[na][nb]) { vis[na][nb] = true; q.push((na, nb)); } } } } }}int main() { int T; scanf("%d", &T); for (int z = 1; z <= T; ++z) { init(); // 处理x轴 sort(xx + 1, xx + 1 + nx); vector
    sorted_x(xx + 1, xx + 1 + nx); int cnt = 0; map
    m_x; int current = 1; for (int i : sorted_x) { if (i != current + 1) { m_x[current] = cnt++; } current = i; } // 处理y轴 sort(yy + 1, yy + 1 + ny); vector
    sorted_y(yy + 1, yy + 1 + ny); int cnt = 0; map
    m_y; int current = 1; for (int i : sorted_y) { if (i != current + 1) { m_y[current] = cnt++; } current = i; } // 标记坏椰子 vector
    > bad_coconuts; // 遍历所有坏椰子,离散化坐标 for (int i = 1; i <= nc; ++i) { int xi = x[i], yi = y[i]; auto mx = m_x[xi]; auto my = m_y[yi]; vis[mx][my] = true; bad_coconuts.push_back(make_pair(xi, yi)); } //DFS遍历 ll sum = 0; for (int xi = 1; xi <= cntx; ++xi) { for (int yi = 1; yi <= cnty; ++yi) { if (!vis[xi][yi]) { ll area = 0; queue
    > q; q.push((xi, yi)); vis[xi][yi] = true; while (!q.empty()) { auto [a, b] = q.front(); q.pop(); for (int k = 0; k < 4; ++k) { int na = a + dx[k]; int nb = b + dy[k]; if (na >=1 && na <= cntx && nb >=1 && nb <= cnty && !vis[na][nb]) { vis[na][nb] = true; q.push((na, nb)); area += linex[m_x[x好+na]] * liney[m_y[y好+nb]]; } } } ans[k++] = area; } } } }}

    代码解释

  • 离散化处理:将网格按行和列分割成更小的段,生成新的坐标系统。
  • 标记坏椰子:使用自定义的访问标记数组,标记掉坏椰子的位置。
  • DFS遍历:从每个未访问的点开始,进行深度优先搜索,计算每个连通块的大小。
  • 结果排序和输出:收集所有连通块的大小,排序后输出结果。
  • 这种方法有效地将大网格问题转化为较小的子问题,确保了计算的高效性。

    上一篇:最长上升子序列【nlogn+路径输出】
    下一篇:hibernate配置【IDEA】

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年05月14日 22时29分00秒