首页 > 其他分享 >P5752 [NOI1999] 棋盘分割题解

P5752 [NOI1999] 棋盘分割题解

时间:2023-03-10 11:03:38浏览次数:58  
标签:P5752 y2 NOI1999 int 题解 sum x2 y1 x1

本文来自我的洛谷博客

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

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

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

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

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


题目大意:

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

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

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

像这样:

可以横切也可以纵切。

样例给的很好。

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

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

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


分析问题:

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

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

小区间汇集成大区间。

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

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

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

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

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

四、状态转移:
我们以下图为例,讲解 \(f(x1,y1,x2,y2,k)\) 是如何被拆分的。

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

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

而下面的部分为定值: \((sum-X)\times(sum-X)/n\) 。

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

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


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

上面部分的定值: \((sum-X)\times(sum-X)/n\) 。

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

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


下面考虑纵切。

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

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

右边的部分为定值: \((sum-X)\times(sum-X)/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,y2,NOI1999,int,题解,sum,x2,y1,x1
From: https://www.cnblogs.com/PlayWithCPP/p/17202641.html

相关文章

  • python工具jupyternotebook页面打开空白问题解决方法
    jupyternotebook页面打开空白问题解决方法下载anaconda自带的jupyternotebook找到这个配置文件C:\Users\Administrator.jupyter\jupyter_notebook_config.py打开找......
  • P7712 [Ynoi2077] hlcpq 题解
    虚式优化建图题。首先有一个很显然的暴力,对于两条相交的线段连一条边,然后跑割点。这个暴力的问题在于边与点的时间复杂度相差过大,无论是空间还是时间都无法承受,所以可以......
  • CF1713F 题解
    题意传送门给出一个从\(1\)到\(n\)的数组\(a\),有一个从\(0\)开始标号的大小为\((n+1)\times(n+1)\)的矩阵\(b\),通过以下方式生成:对于\(0\lei\len\),\(b_{i......
  • 江南信息学2023第三周练习20230310 题解
    比赛链接1001:三个数的最大值条件判断,如判断a最大就是a>=b&&a>=c,以此类推1002:星期几取余,n%7结果是0则是周一,是1则周二,以此类推1003:奇偶分家设两个求和变量sum1,sum2......
  • ABC292F题解
    首先先钦定\(a\leb\),否则交换一下就行。方法1:二分答案。容易发现,答案至少为\(a\),并且用左下角为一个顶点一定不会更劣,并且另外两个点一定都在线段上(否则可以调整)。我们......
  • CF207C3 Game with Two Trees 题解
    脑子不够,科技来凑。不过好像也没有用多么高级的科技……首先这个题目很坏,它让你翻转\(S_{t_2}\)。即从\(t_2\)某个节点往下走到另一个节点的路径所表示的字符串。这个......
  • Python自动化登录验证码问题解决
     1.测试环境中通常解决验证码问题的方法 在测试环境中我们通常通过各种手段来逃避或者获得验证,而这些手段主要是要求开发者在开发的时候留有一定的后门。下面简述几种......
  • 【题解】ARC157 A-D
    因为有的题代码没写出来,所以代码就先咕咕咕了。A.XXYYX题目分析:可以发现每一个XY必然伴随着出现一次YX,当然可能会有一个XY没有伴随的YX的。而且若必须存在XX......
  • 【题解】[Ynoi2015] 我回来了
    题目分析:所谓的期望乘以\(R-L+1\)其实就是求亵渎的触发次数,因为我们能选择的伤害只有\(R-L+1\)种。有一个很显然的转化,就是对于伤害\(d\),我们以随从的血量......
  • DP练习1题解
    这是2023.3.7DP题单十个题的题解。T1ColoredSubgraphs(CF1796E)简要题意:给定一棵树,你要对树进行链剖分,必须剖成上下竖直的链,求剖后最短链的长度最大值。最小值最大......