本文来自我的洛谷博客

这个题解思路虽然与其他人的思路相同,

但力求使用清晰易懂的图片和文字,讲解最简洁的道理。

请大家耐心地看完,注意要结合图片一起哦~~

2022-8-24 更改了格式与错别字。

2022-8-28 更改了数学公式格式。

这是本蒟蒻第一次写题解,不足之处请多包涵。


题目大意:

读完题的可以跳过这一部分。

给定一个矩阵,每个位置上都有数字。

可以分割 \(n-1\) 次,每次分割为 \(2\) 个矩形,然后把一半放在一旁,然后在另外一半继续割。

像这样:

可以横切也可以纵切。

样例给的很好。

然后就分为 \(n\) 块(因为割了 \(n-1\) 次)。

记 \(X=\dfrac{s}{n}\),\(s\) 为矩阵中所有的数字之和。

设第 \(i\) 块的和为 \(x_i\),那么求出怎样割才能使 $\sum_{i=1}{n}(x_i-X)2 $ 更小。


分析问题:

我们看到这种分割问题,最后组合起来求总体最优值,便可以立马联想到区间 DP。这叫望梅止渴做 DP 问题的复杂反射。

毕竟区间 DP 的主要思想就是大区间包含小区间,

小区间汇集成大区间。

好了,废话不多说,我们先从如下几个角度思考:

  • 状态表示
  • 状态含义
  • 目标状态
  • 状态转移

一、状态表示:\(f(x1,y1,x2,y2,k)\)。

二、状态含义:\(f(x1,y1,x2,y2,k)\) 表示求解子矩阵 \((x1,y1)\sim(x2,y2)\) 割了 \(k\) 刀得来的最优解(即下图框住区域的最优解)。

三、目标状态:\(f(1,1,8,8,n)\),即求解整个矩阵被割了 \(n\) 刀的最优解。

四、状态转移:

我们以下图为例,讲解 \(f(x1,y1,x2,y2,k)\) 是如何被拆分的。

①:考虑选择上面继续割(如下图),丢掉下面的,其分界线为第 \(i\) 行。

所以应该取上面的最优值,同时少割一刀:\(f(x1,y1,i,y2,k-1)\),

而下面的部分为定值:\(\dfrac{(sum-X)^2}{n}\)。

\(sum\) 为下面的部分所有格子的和。

这两个部分合起来就是 \(f(x1,y1,x2,y2,k)\)。


②:考虑选择下面继续割(如上图)。

上面部分的定值:\(\dfrac{(sum-X)^2}{n}\)。

下面的最优值:\(f(i+1,y1,x2,y2,k-1)\)。

\(sum\) 为上面的部分所有格子的和。


下面考虑纵切。

③:考虑选择左边继续割(如上图),分界线为第 \(i\) 列。

取左边的最优值:\(f(x1,y1,x2,i,k-1)\),

右边的部分为定值:\(\dfrac{(sum-X)^2}{n}\)。

\(sum\) 为右边的部分所有格子的和。


④:考虑选择右边继续割(如上图)。

取右边的最优值:\(f(x1,i+1,x2,y2,k-1)\),

左边的部分为定值:\((sum-X)\times(sum-X)/n\),

\(sum\) 为左边的部分所有格子的和。


我们每次取一个值,其实都是在将问题规模缩小。

情况考虑清楚了,那怎么从一个 \(f\) 到另一个 \(f\) 呢,如果是用普通的区间 DP,那估计要使用 \(5\) 层甚至更多的循环,所以,我们使用万能的记忆化搜索,免去繁琐的循环结构。


综上所述,

我们便实现了对大区间的拆分。

而我们不断提到 \(sum\),是一块区域的和,那么,我们可以使用二维前缀和来维护。相信大家一定会。

好了,上 AC 代码。

#include <bits/stdc++.h>

using namespace std;

const int N=15;
const double INF=1e10; //因为要求min,所以要定义INF int n;
int m=8;
double X; //平均值
double s[N][N]; //记录每个格子的值
double f[N][N][N][N][N]; //状态 double GetSum(int x1,int y1,int x2,int y2)//求[x1,y1]~[x2,y2]的和,为下文的GetX服务
{
return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
} double GetX(int x1,int y1,int x2,int y2)// 计算上文的(sum−X)×(sum−X)/n。
{
return (GetSum(x1,y1,x2,y2)-X)*(GetSum(x1,y1,x2,y2)-X)/n;
} double DFS(int x1,int y1,int x2,int y2,int k)//使用记忆化搜索进行递归调用
{
double& v=f[x1][y1][x2][y2][k];//因为太难写了,所以给f[x1][y1][x2][y2][k]建立引用
if(v>=0)return v; //已经访问过该点了,直接返回
if(k==1)return v=GetX(x1,y1,x2,y2);//最后一块,不可能再割了 v=INF; //为求最小值做准备 for(int i=x1;i<x2;i++) //下面是刚刚讨论的结果
{
v=min(v,DFS(x1,y1,i,y2,k-1)+GetX(i+1,y1,x2,y2));
v=min(v,DFS(i+1,y1,x2,y2,k-1)+GetX(x1,y1,i,y2));
} for(int i=y1;i<y2;i++)
{
v=min(v,DFS(x1,y1,x2,i,k-1)+GetX(x1,i+1,x2,y2));
v=min(v,DFS(x1,i+1,x2,y2,k-1)+GetX(x1,y1,x2,i));
} return v;
} int main()
{
scanf("%d",&n);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
double x;
scanf("%lf",&x);
s[i][j]=s[i-1][j]+s[i][j-1]+x-s[i-1][j-1]; //建立前缀和
}
}
X=s[m][m]/n; //求平均值
memset(f,0x80,sizeof f); //初始化
printf("%.3f\n",sqrt(DFS(1,1,m,m,n)));//注意,一定要根号啊啊啊!!!
return 0;
}

P5752 [NOI1999] 棋盘分割题解的更多相关文章

  1. [NOI1999] 棋盘分割

    COGS 100. [NOI1999] 棋盘分割 http://www.cogs.pro/cogs/problem/problem.php?pid=100 ★★   输入文件:division.in  ...

  2. POJ1991 NOI1999棋盘分割

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15581   Accepted: 5534 Description ...

  3. [NOI1999] 棋盘分割(推式子+dp)

    http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 156 ...

  4. 【Luogu】P1436 棋盘分割 题解

    嗯,点开题目,哇!是一道闪亮亮的蓝题! 不要被吓到了,其实,这道题就是一个简单的DP啦! 我们设 \(f[x1][y1][x2][y2][c]\) 为以 \((x1,y1)\) 为左上角,以 \((x ...

  5. POJ 1191 棋盘分割

    棋盘分割 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11213 Accepted: 3951 Description 将一个 ...

  6. poj 1191 棋盘分割 动态规划

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11457   Accepted: 4032 Description ...

  7. NOI 193棋盘分割.cpp

    193:棋盘分割 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分 ...

  8. HDU 2517 / POJ 1191 棋盘分割 区间DP / 记忆化搜索

    题目链接: 黑书 P116 HDU 2157 棋盘分割 POJ 1191 棋盘分割 分析:  枚举所有可能的切割方法. 但如果用递归的方法要加上记忆搜索, 不能会超时... 代码: #include& ...

  9. POJ 1191棋盘分割问题

    棋盘分割问题 题目大意,将一个棋盘分割成k-1个矩形,每个矩形都对应一个权值,让所有的权值最小求分法 很像区间DP,但是也不能说就是 我们只要想好了一个怎么变成两个,剩下的就好了,但是怎么变,就是变化 ...

  10. 洛谷 P1436 棋盘分割 解题报告

    P1436 棋盘分割 题目描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的两部分中的任意一块继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共 ...

随机推荐

  1. DolphinDB +Python Airflow 高效实现数据清洗

    DolphinDB 作为一款高性能时序数据库,其在实际生产环境中常有数据的清洗.装换以及加载等需求,而对于该如何结构化管理好 ETL 作业,Airflow 提供了一种很好的思路.本篇教程为生产环境中 ...

  2. TS(一)环境搭建与基本类型

    1 TypeScript 环境搭建 1 准备NodeJs环境 2 npm全局安装typeScript npm i -g typescript 3 编写一个ts文件 4 使用tsc命令编译ts文件为js ...

  3. 通过命令快速找到python的路径

    查询Python 首先我们需要知道Python安装路径,可以在命令行中逐行执行下面代码 python3 import sys sys.executable

  4. Python pip速度慢,更换源

    版权声明:本文为CSDN博主「cocoprince」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/Coco ...

  5. es6的Symbol数据类型

    ES6引入了一种新的原始数据类型Symbol,表示独一无二的值.它是JavaScript语言的第七种数据类型,前六种是:Undefined.Null.布尔值(Boolean).字符串(String). ...

  6. pyhton内置函数

    内置函数 1.type(变量名)-> class 查看变量的数据类型 2.print(self, *args, sep=' ', end='\n', file=None) sep:指定多个参数以 ...

  7. 文盘Rust -- rust连接oss

    作者:京东科技 贾世闻 对象存储是云的基础组件之一,各大云厂商都有相关产品.这里跟大家介绍一下rust与对象存储交到的基本套路和其中的一些技巧. 基本连接 我们以 aws 对象存储的sdk为例来说说基 ...

  8. OpenResty学习笔记03:再探WAF

    一. 再谈WAF 我们上一篇安装的WAF来自另一位技术大神 赵舜东,花名 赵班长,一直从事自动化运维方面的架构设计工作.阿里云MVP.华为云MVP.中国SaltStack用户组发起人 .新运维社区发起 ...

  9. IPS 和 IDS

    IPS/IDS 什么是IPS和IDS IDS/IPS是检测和防止对网络服务器进行未授权的访问的系统.有许多产品同时有IDS和IPS的作用,作为加强企业信息安全所必须的系统 什么是IDS(Intrusi ...

  10. 2022-08-10:为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机, 游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1, 初始有一个小球在编号 0 的弹簧处。若小球在编号为 i 的弹

    2022-08-10:为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机, 游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1, 初始有一个小球在编号 0 的弹簧处.若小球在编号为 i 的弹 ...