[BZOJ1048][HAOI2007]分割矩阵(数学相关+记搜)

本文介绍了一个关于棋盘分割的问题,目标是最小化分割后的子矩形权值均方差。通过动态规划的方法,实现了有效的解决方案,并给出了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

传送门

题目大意:给出一个n*m的棋盘,每一个格子有一个权,切n-1刀,变成n个子矩形,每一个子矩形的权为所有格子的权值和,求一种方案使这些子矩形的均方差最小。

题解

均方差的化简方法同棋盘分割:http://blog.youkuaiyun.com/clove_unique/article/details/52936610
f(i,a,b,c,d)表示还有i刀可切,当前的矩形为(a,b,c,d)的最小值
由于切开的两个矩形都可以再切,写记搜方便一些

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 15

int x,y,n,inf,Min,s[N][N],f[N][N][N][N][N];
double xba,ans;

int qr(int x){return x*x;}
int dp(int id,int a,int b,int c,int d)
{
    int re=f[id][a][b][c][d];
    if (re!=inf) return re;
    for (int mid=a;mid<c;++mid)
        for (int i=0;i<id;++i)
        {
            int p=dp(i,a,b,mid,d);
            int q=dp(id-1-i,mid+1,b,c,d);
            if (p!=inf&&q!=inf) re=min(re,p+q);
        }
    for (int mid=b;mid<d;++mid)
        for (int i=0;i<id;++i)
        {
            int p=dp(i,a,b,c,mid);
            int q=dp(id-1-i,a,mid+1,c,d);
            if (p!=inf&&q!=inf) re=min(re,p+q);
        }
    f[id][a][b][c][d]=re;
    return re;
}
int main()
{
    scanf("%d%d%d",&x,&y,&n);;
    for (int i=1;i<=x;++i)
        for (int j=1;j<=y;++j)
        {
            int x;scanf("%d",&x);
            s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+x;
        }
    memset(f,127,sizeof(f));inf=f[0][0][0][0][0];
    for (int a=1;a<=x;++a)
        for (int b=1;b<=y;++b)
            for (int c=a;c<=x;++c)
                for (int d=b;d<=y;++d)
                    f[0][a][b][c][d]=qr(s[c][d]-s[c][b-1]-s[a-1][d]+s[a-1][b-1]);
    Min=dp(n-1,1,1,x,y);
    xba=(double)s[x][y]/(double)n;
    ans=(double)Min/(double)n-xba*xba;
    printf("%.2lf\n",sqrt(ans));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值