321. 棋盘分割

题目链接

321. 棋盘分割

将一个 8×8 的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了 (n1) 次后,连同最后剩下的矩形棋盘共有 n 块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)
image

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。

现在需要把棋盘按上述规则分割成 n 块矩形棋盘,并使各矩形棋盘总分的均方差最小。

均方差image,其中平均值imagexi 为第 i 块矩形棋盘的总分。

请编程对给出的棋盘及 n,求出均方差的最小值。

输入格式

1 行为一个整数 n

2 行至第 9 行每行为 8 个小于 100 的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。

输出格式

输出最小均方差值(四舍五入精确到小数点后三位)。

数据范围

1<n<15

输入样例:

3 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 3

输出样例:

1.633

解题思路

区间dp

二维平面上的区间dp:

  • 状态表示:f[x1][y1][x2][y2][k] 表示左上角为 (x1,y1),右上角为 (x2,y2) 的子矩阵含有 k 个小矩阵的最小 (xiX)2n,其中 X 为整个矩阵分为 n 块的平均值

  • 状态计算,令 t=f[x1][y1][x2][y2][k],其中 get 函数获取矩阵面积:

  • 横向切:

    • t=min(t,dp(i+1,y1,x2,y2,k1)+get(x1,y1,i,y2))
    • t=min(t,dp(x1,y1,i,y2,k1)+get(i+1,y1,x2,y2))
  • 纵向切:

    • t=min(t,dp(x1,i+1,x2,y2,k1)+get(x1,y1,x2,i))
    • t=min(t,dp(x1,y1,x2,i,k1)+get(x1,i+1,x2,y2))
  • 时间复杂度:(n×85)

代码

// Problem: 棋盘分割 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/323/ // Memory Limit: 10 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=16,M=9; int n; double f[M][M][M][M][N],s[M][M],X=0; double get(int x1,int y1,int x2,int y2) { double sum=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]; sum-=X; return sum*sum/n; } double dp(int x1,int y1,int x2,int y2,int k) { double &t=f[x1][y1][x2][y2][k]; if(t>=0)return t; if(k==1)return t=get(x1,y1,x2,y2); t=2e9; for(int i=x1;i<x2;i++) { t=min(t,dp(i+1,y1,x2,y2,k-1)+get(x1,y1,i,y2)); t=min(t,dp(x1,y1,i,y2,k-1)+get(i+1,y1,x2,y2)); } for(int i=y1;i<y2;i++) { t=min(t,dp(x1,i+1,x2,y2,k-1)+get(x1,y1,x2,i)); t=min(t,dp(x1,y1,x2,i,k-1)+get(x1,i+1,x2,y2)); } return t; } int main() { cin>>n; for(int i=1;i<M;i++) for(int j=1;j<M;j++) { cin>>s[i][j]; X+=s[i][j]; s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1]; } X/=n; memset(f,-1,sizeof f); printf("%.3lf",sqrt(dp(1,1,8,8,n))); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16012300.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示