BZOJ 1048: [HAOI2007]分割矩阵

Posted czy020202

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1048: [HAOI2007]分割矩阵相关的知识,希望对你有一定的参考价值。

1048: [HAOI2007]分割矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 1077  Solved: 776

[Submit][Status][Discuss]

Description

  将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了n个矩阵。(每次分割都只能沿着数字间的缝隙进行)原矩阵中每一位置上有一个分值,一个矩阵的总分为其所含各位置上分值之和。现在需要把矩阵按上述规则分割成n个矩阵,并使各矩阵总分的均方差最小。请编程对给出的矩阵及n,求出均方差的最小值。

Input

第一行为3个整数,表示a,b,n(1<a,b<=10,1<n<=10)的值。
第二行至第n+1行每行为b个小于100的非负整数,表示矩阵中相应位置上的分值。每行相邻两数之间用一个空
格分开。

Output

仅一个数,为均方差的最小值(四舍五入精确到小数点后2位)

Sample Input

5 4 4
2 3 4 6
5 7 5 1
10 4 0 5
2 0 2 3
4 1 1 1

Sample Output

0.50

题解

方差公式为sqrt(((x1-ave)^2+(x2-ave)^2+…+(xn-ave)^2)/n)

ave可以直接得到。

因为a,b,n<=10,那么可以直接记忆化搜索,设f[x1][y1][x2][y2][k]为以(x1,y1)为左上角,(x2,y2)为右下角的矩形分成k个矩形最小的(s-ave)^2的和(s为k个小矩形各自的分值)。

那么最终答案是sqrt(f[1][1][a][b][n]/n)。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=15,inf=0x3f3f3f3f;
int a,b,n,sum;
int map[N][N],s[N][N];
double ave;
double f[N][N][N][N][N];
double sqr(double x){
	return x*x;
}
double dfs(int x1,int y1,int x2,int y2,int n){
	if(f[x1][y1][x2][y2][n]!=-1)return f[x1][y1][x2][y2][n];
	f[x1][y1][x2][y2][n]=inf;
	if(n==1){
		return f[x1][y1][x2][y2][1]=sqr((s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])-ave);
	}
	for(int i=x1;i<x2;i++){
		for(int j=1;j<n;j++){
			f[x1][y1][x2][y2][n]=min(f[x1][y1][x2][y2][n],dfs(x1,y1,i,y2,j)+dfs(i+1,y1,x2,y2,n-j));
		}
	}
	for(int i=y1;i<y2;i++){
		for(int j=1;j<n;j++){
			f[x1][y1][x2][y2][n]=min(f[x1][y1][x2][y2][n],dfs(x1,y1,x2,i,j)+dfs(x1,i+1,x2,y2,n-j));
		}
	}
	return f[x1][y1][x2][y2][n];
}
int main(){
	scanf("%d%d%d",&a,&b,&n);
	for(int i=1;i<=a;i++){
		for(int j=1;j<=b;j++){
			scanf("%d",&map[i][j]);
			sum+=map[i][j];
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+map[i][j];
		}
	}
	ave=(double)sum/n;
	for(int i=1;i<=a;i++){
		for(int j=1;j<=b;j++){
			for(int k=i;k<=a;k++){
				for(int l=j;l<=b;l++){
					for(int m=1;m<=n;m++){
						f[i][j][k][l][m]=-1;
					}
				}
			}
		}
	}
	printf("%.2lf",sqrt(dfs(1,1,a,b,n)/n));
	return 0;
}

以上是关于BZOJ 1048: [HAOI2007]分割矩阵的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj1048] [HAOI2007]分割矩阵

1048: [HAOI2007]分割矩阵

[HAOI2007]分割矩阵

P2217 [HAOI2007]分割矩阵

BZOJ 1047 HAOI2007 理想的正方形 单调队列

bzoj1047[HAOI2007]理想的正方形 二维RMQ