您的位置:首页 > 其它

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

2017-05-03 17:24 393 查看

题目描述

传送门

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

题解

均方差的化简方法同棋盘分割:http://blog.csdn.net/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

,f

;
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));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: