当前位置: 首页 > news >正文

【题解】洛谷 P1169 [ZJOI2007] 棋盘制作 [思维 + dp]

P1169 [ZJOI2007] 棋盘制作 - 洛谷

我不会告诉你这道题我做了多久。


注意到数据范围,正解应该是 O(MN) 的时间复杂度。

单纯枚举长方形是 O(M^2N^2),肯定是要做些什么前缀和 / 预处理来降低下的。

二维预处理后转移考虑 dp,整体要满足 “局部最优达成整体最优 / 整体最优能从局部最优继承”

那应该怎么定义?

我就是在这一步走歪的,定义了 dp[i][j]:以 (i, j) 为右下角的最大合法矩阵的行范围和列范围。

但其实有一个很明显的问题:如果有面积相等的两个矩阵,应该选哪个?

由于后面的状态是否合法还要看当前状态的边界,所以说这样做是有后效性的

所以这种方法从一开始就是错误的,这警示我们打一切 dp 之前都要仔细证明有无后效性

(我就这样调了好久找不出错,,小数据都对 70 分。)

不管怎样,不能再以点作为结束点 / 边界了。

但是肯定是要有边界的,比如说以某一行 or 某一列。

这样转移下一行 / 列时边界对接都是固定的,不会产生后效性。

考虑以行作为边界,预处理 up 数组作为 (i, j) 往上(更小的行)可合法的格子数。

但这还不够,我们需要知道当前行合法的格子范围,于是再定义两个数组记录该行合法范围。

注意到一行的合法范围不止一段,那么再细节点,定义:

int lef[N][N], rig[N][N];
// lef[i][j]:第 i 行从 (i,j) 向左能延伸到的合法最左列(满足黑白交替)
// rig[i][j]:第 i 行从 (i,j) 向右能延伸到的合法最右列(满足黑白交替)

状态转移时,我们有:

// 如果不是第一行,且当前格与上方格颜色不同if(i > 1 && mat[i][j] != mat[i - 1][j]) {up[i][j] = up[i - 1][j] + 1;// 当前悬线可以向上延伸:高度 + 1lef[i][j] = max(lef[i][j], lef[i - 1][j]);// 左边界取当前行与上一行的更靠右者(取 max,因为 left 值越小越靠左)rig[i][j] = min(rig[i][j], rig[i - 1][j]);// 右边界取当前行与上一行的更靠左者(取 min,因为 right 值越大越靠右)}// 当前悬线能覆盖的横向宽度int width = rig[i][j] - lef[i][j] + 1;// 正方形边长受限于宽度和高度中的较小值int side = min(width, up[i][j]);// 更新最大正方形面积(边长平方)s_ans = max(s_ans, side * side);// 更新最大矩形面积(宽 × 高)r_ans = max(r_ans, width * up[i][j]);

发现这样转移出来的是个倒着的 “T” 字形,想要变成矩阵,还要满足:

// 预处理每行的 left:若当前格与左边格颜色不同,则可继承左边的左边界for (int i = 1; i <= n; i ++) {for (int j = 2; j <= m; j ++) if (mat[i][j] != mat[i][j - 1]) {lef[i][j] = lef[i][j - 1]; // 向左扩展}}// 预处理每行的 right:若当前格与右边格颜色不同,则可继承右边的右边界for (int i = 1; i <= n; i ++) {for (int j = m - 1; j >= 1; j --) if (mat[i][j] != mat[i][j + 1]) {rig[i][j] = rig[i][j + 1]; // 修正:应为 j+1,不是 j-1}}

即预处理时就要定义 lef 和 rig 是可以和上一行贴合的,保证后面每一次转移都合法。

就这样做完了,完整代码请翻到最后面。

关于这种状态转移比较诡异的 dp,我们其实有一个专门的算法:悬线法

注释里也写了,up 数组就是 “悬线”。顾名思义,是从上面往下悬的一整列合法格子。

然后标准过程就如本题,预处理俩数组然后美美转移。

只要满足以下几点,就是悬线法题目:

(1)求最大子矩形
(2)合法性具有“垂直可继承性”(有悬线可处理)
(3)行内合法性可预处理(可降低时间复杂度)
(4)约束是局部的(相邻之间)

再使用点,以下三个问题都满足,即可用悬线:

  1. 是不是在 0 / 1(或有限颜色)矩阵中找最大矩形?
  2. “合法”是否只依赖相邻格子(上下左右)?
  3. 数据范围是否允许 O(MN)

完整代码:

// 代码来自本人,注释由千问 AI 生成 + 人工修改 
#include<bits/stdc++.h>
using namespace std;const int N = 2010;int mat[N][N];
// mat[i][j]:原始棋盘颜色(0/1)int lef[N][N], rig[N][N];
// lef[i][j]:第 i 行从 (i,j) 向左能延伸到的合法最左列(满足黑白交替)
// rig[i][j]:第 i 行从 (i,j) 向右能延伸到的合法最右列(满足黑白交替)int up[N][N];
// up[i][j]:从 (i,j) 向上能延伸的连续黑白交替格子数(即 "悬线" 高度)int main() {ios::sync_with_stdio(false);cin.tie(0);int n, m;cin >> n >> m; // 读入棋盘,并初始化 left / right / upfor (int i = 1; i <= n; i ++) {for (int j = 1; j <= m; j ++) {cin >> mat[i][j];lef[i][j] = rig[i][j] = j;   // 初始时左右边界都是自己up[i][j] = 1;                   // 初始高度为 1(仅当前格)}}// 预处理每行的 left:若当前格与左边格颜色不同,则可继承左边的左边界for (int i = 1; i <= n; i ++) {for (int j = 2; j <= m; j ++) if (mat[i][j] != mat[i][j - 1]) {lef[i][j] = lef[i][j - 1]; // 向左扩展}}// 预处理每行的 right:若当前格与右边格颜色不同,则可继承右边的右边界for (int i = 1; i <= n; i ++) {for (int j = m - 1; j >= 1; j --) if (mat[i][j] != mat[i][j + 1]) {rig[i][j] = rig[i][j + 1]; // 修正:应为 j+1,不是 j-1}}int s_ans = 0, r_ans = 0;    // 正方形面积和长方形面积 for (int i = 1; i <= n; i ++) {for (int j = 1; j <= m; j ++) {// 如果不是第一行,且当前格与上方格颜色不同if(i > 1 && mat[i][j] != mat[i - 1][j]) {up[i][j] = up[i - 1][j] + 1;// 当前悬线可以向上延伸:高度 + 1lef[i][j] = max(lef[i][j], lef[i - 1][j]);// 左边界取当前行与上一行的更靠右者(取 max,因为 left 值越小越靠左)rig[i][j] = min(rig[i][j], rig[i - 1][j]);// 右边界取当前行与上一行的更靠左者(取 min,因为 right 值越大越靠右)}// 当前悬线能覆盖的横向宽度int width = rig[i][j] - lef[i][j] + 1;// 正方形边长受限于宽度和高度中的较小值int side = min(width, up[i][j]);// 更新最大正方形面积(边长平方)s_ans = max(s_ans, side * side);// 更新最大矩形面积(宽 × 高)r_ans = max(r_ans, width * up[i][j]);}}cout << s_ans << "\n" << r_ans << "\n";return 0;
}

http://www.dtcms.com/a/540995.html

相关文章:

  • 音频限幅器D2761使用手册
  • 网站金融模版wordpress轮播代码
  • 【工具推荐】电脑手机多端互通协作实用
  • 一般网站的跳出率dede做双语网站
  • 自己制作的网站如何发布建筑设计公司经营范围有哪些
  • 51c大模型~合集39
  • 操作【GM3568JHF】FPGA+ARM异构开发板 使用指南:串口
  • 【牛客CM11】链表分割
  • .NET 对象转Json的方式
  • 广西住建局官方网站大数据营销的应用领域
  • Linux ioctl 深度剖析:从原理到实践
  • 网站备案流程解答做最漂亮的网站
  • LED驱动电路(三)
  • Keil工程编译垃圾清理
  • 同城跑腿APP源码开发技术全景:即时订单、骑手定位与路线优化算法
  • 【数据工程】15. Stream Query Processing
  • 鄂州网站设计效果wordpress comment_form_after
  • 爱网站关键词查询工具潍坊营销网站
  • java程序生成pdf或wod乱码
  • 做网站和游戏是如何赚钱crm系统开发
  • 网页pdf下载攻略--以混元上传的pdf为例
  • AI在处理扫描版PDF时准确率低,如何提升?
  • 网站做成软件免费wordpress 首页制作
  • 所有网站打不开深圳做app网站的公司名称
  • centos 7 redhat7 升级内核 升级内核到5.4版本 202510试过可以成功
  • 什么是TC8?
  • EtherNet/IP转ProfiNet智能网关配置指南:西门子1500PLC与多台机器人通讯
  • 【仿真测试】基于FPGA的完整BPSK通信链路实现,含频偏锁定,帧同步,定时点,Viterbi译码,信道,误码统计
  • 晨控CK-UR08-E01与汇川AC系列PLC配置EtherNet/IP通讯连接手册
  • 稀疏Ax=b超静定方程的常用解法介绍