首页 > 其他分享 >joi2022_yo2_c 国土分割 (Land Division) 题解

joi2022_yo2_c 国土分割 (Land Division) 题解

时间:2024-07-09 18:30:47浏览次数:10  
标签:Division 分割 Land int 题解 sum 矩阵 cnt leqslant

国土分割 (Land Division)

推销我的洛谷博客。

题意

给定一个 \(n \times m\) 的矩阵 \(a\),你需要选择在横向或纵向分割至少一次,使得每个分割出来的小矩阵的 \(a_{i,j}\) 之和相等。

数据范围

  • \(1 \leqslant n,m \leqslant 50\)。
  • \(1 \leqslant a_{i, j} \leqslant 10^5\)。

思路

闲话

老师给我们复现了一下,场切了,心路历程如下。

第一眼:好像有些难度啊。

第二眼:\(1\leqslant n,m \leqslant 50\),这不是水题吗。

第三眼:欸如果 \(a_{i,j}=0\) 怎么办。

第四眼:哦 \(a_{i,j} \geqslant 1\),那没事了。

正题

看起来挺吓唬人,但数据范围太小,所以考虑枚举。

枚举最左上角的小矩阵的大小,假设这个矩阵的右下角为 \((x,y)\),那么我们就知道了每个矩阵的 \(a_{i,j}\) 之和。

那么对于列的分割方法,你可以通过前 \(x\) 行的信息推出要在哪些列进行分割。同理,你可以推出要在哪些行进行分割,判断是否合法即可。

  • 对于一组 \((x,y)\) 有几种分割方式呢?正如闲话中所说的,\(a_{i,j}\) 都为正数,那么可以发现对于每一组 \((x,y)\) 都至多有一种分割方案。

  • 对于求一个矩阵的 \(a_{i,j}\) 之和,不难想到二维前缀和优化。

详细见代码。

复杂度

  • 时间:\(O(n^2\times m^2)\)。
  • 空间:\(O(n\times m)\)。

Code

点击查看代码
#include <bits/stdc++.h>

using namespace std;

int n, m, a[55][55], sum[55][55], cnt, stk[55], top, ans;

int C (int x, int y, int a, int b) { // 二维前缀和求解矩阵和
  return sum[a][b] - sum[x - 1][b] - sum[a][y - 1] + sum[x - 1][y - 1];
}

void Solve (int i, int j) { // 对于一组 (i, j),判断是否具有合法的分割方案
  cnt = C(1, 1, i, j), top = 1, stk[1] = j; // cnt 为每个矩阵的和,stk 用于记录在哪些列需要分割
  for (int k = j + 1; k <= m; k++) { // 利用前 i 行推出在哪些列需要分割
    if (C(1, stk[top] + 1, i, k) == cnt) { // 找出来了一个矩阵
      stk[++top] = k;
    } else if (C(1, stk[top] + 1, i, k) > cnt) { // 不合法
      return ;
    }
  }
  if (stk[top] != m) { // 最右上角的矩阵和没有达到 cnt
    return ;
  }
  int lst = i;
  for (int k = i + 1; k <= n; k++) { // 已知在哪些列需要分割,推在哪些行需要分割
    bool f = 0;
    for (int l = 1; l <= top; l++) {
      if (C(lst + 1, stk[l - 1] + 1, k, stk[l]) < cnt) { // 这一行还不够
        f = 1;
      } else if (C(lst + 1, stk[l - 1] + 1, k, stk[l]) > cnt) { // 这一行有矩阵和已经超过了 cnt,不可能合法
        return ;
      }
    }
    if (!f) { // 找到了满足要求的一行
      lst = k;
    }
  }
  if (lst != n) { // 最下方的矩阵还不合法
    return ;
  }
  // cout << i << ' ' << j << '\n';
  ans++;
}

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  //freopen("div.in", "r", stdin);
  //freopen("div.out", "w", stdout);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      cin >> a[i][j], sum[i][j] = sum[i][j - 1] + a[i][j];
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      sum[i][j] += sum[i - 1][j]; // 逐维前缀和
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      Solve(i, j);
    }
  }
  cout << ans - 1; // 由于题目要求至少分割一次,则需要减去 (n, m) 这一组
  return 0;
}

标签:Division,分割,Land,int,题解,sum,矩阵,cnt,leqslant
From: https://www.cnblogs.com/wnsyou-blog/p/18292535/joi2022_yo2_c

相关文章

  • 题解 - 幻象迷宫
    题目in洛谷或题目inCF题目幻象迷宫可以认为是无限大的,不过它由若干个\(N\timesM\)的矩阵重复组成。矩阵中有的地方是道路,用\(\verb!.!\)表示;有的地方是墙,用\(\verb!#!\)表示。起始位置用\(\verb!S!\)表示。也就是对于迷宫中的一个点\((x,y)\),如果\((x\bmodn,y......
  • UVA12342 Tax Calculator 题解
    题目传送门题目大意题目描述某国所得税计算十分复杂。该国政府指定你制作一个自动计算所得税的程序。以下是该国计算所得税的规则:所得税免征额为180000180000......
  • P10719 的题解
    (一)设\(a_{x,y}\)为从\((1,1)(x,y)\)矩形中的\(1\)的数量。然后通过二位前缀和可以\(O(1)\)算。注意到\(1\len,m\le100\)。先确定矩形右下角,对于左上角,先确定在哪一行,再二分在哪一列。(二)AC代码。#include<bits/stdc++.h>#definepbpush_back#definefifirs......
  • 【Py/Java/C++三种语言OD独家2024D卷真题】20天拿下华为OD笔试之【前缀和/固定滑窗】2
    有LeetCode算法/华为OD考试扣扣交流群可加948025485可上欧弟OJ系统练习华子OD、大厂真题绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)文章目录题目描述与示例题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明解题思路贪心思想......
  • zxx题单的题解
    https://www.luogu.com.cn/training/168096CF1359ELemma:\(\forallx\in\mathbb{N},\x\bmoda\bmodb=x\bmodb\bmoda\iffa\midb\(a<b)\)Proof:因为\(a<b\),所以\(x\bmoda\bmodb=x\bmoda\)。设\(x=pb+q\),其中\(0<q<b......
  • PostgreSQL的AutoVacuum原理及autovacuum不工作问题解析
    1、AutoVacuum概述PostgreSQL数据库是有数据清理的,有人工执行清理,也有自动清理,但是这2种的清理方式对性能是有不同的影响,特别是OLTP环境中,每次不管是人工清理还是自动清理deadtuple,都会对数据库的IO有明显的影响,基于PostgreSQL的原理每个表中的行会存在多个版本的数据,为了完成......
  • 2024码蹄杯职高省赛第三场初赛全题解
    其实吧对于码蹄杯省赛的话,第三场是一千五百多人,百分之25的获奖率,然后前四百名左右就可以获奖,根据排行来看大概是六题左右,其中大概就四题要点脑子,其余的基本上属于语法题,也就是13题中如果语法没问题的话,九题是很轻松的,因为都是青铜白银题,语法没问题的话就OK的,然后就是一个P序列,......
  • 题解(2024.7.8贪心)
    1.Teleporters(HardVersion)题意:有n+2个位置:0~n+1,给定n个数\(a_1\)~\(a_n\),有以下操作:向左/右移动一格,代价为1。传送回0位置或者n+1位置,记你当前的位置为i,则代价为\(a_i\)。每个位置只能发动一次传送。求最大传送次数思路:因为每次传送都会回到0/n+1号点,所以,到......
  • 基础算法训练题单之排序(从入门到入土)——题解
    A.P1177【模板】排序三种方法:快速排序,归并排序,STL库的sort函数。法一、三:https://www.cnblogs.com/expect-999/p/17594345.html法二:https://www.cnblogs.com/expect-999/p/17599008.htmlB.P1923【深基9.例4】求第k小的数模板题目,直接对数组进行升序排序,如果数组从......
  • Codeforces Round 953(Div.2) 题解(A-E)
    CodeforcesRound953(Div.2)题解(A-E)A题意Alice有n本书,第一本书有\(a_1\)页,序号为1,第二本书有\(a_2\)页,序号为2,……,第n本书有\(a_n\)页,序号为n。Alice将把所有书分成两堆,并阅读每一堆中序号最大的一本书。Alice喜欢读书,请你告诉她,她最多可以读多少页的书。Solution第......