[HAOI2007]分割矩阵

  06年一道均分数据的随机化,07年的这道题又是划分,又是方差最小。话说我第一眼看到懵了一下,二维随机化???

  然而这道题是矩阵,且是一刀一刀切割的,应该是DP,但是我也没啥思路。

  正解是记忆化搜索吧,搜索说好打也好打,但是不好调啊,要注意细节。

  本题可以用 f[a][b][c][d][k] 表示把左下 (a,b),右上 (c,d) 的矩形切 k 刀的最优解。

  对每一步有两种切割方式。

  1:横切。分成 (a,b) & (c,i) 和 (a,i+1) & (c,d) 两个矩形。

  2:竖切。分成 (a,b) & (i,d) 和 (i+1,b) & (c,d) 两个矩形。

  再有需要注意的一点是状态中还有一维 k ,所以在切完这一刀后,还要枚举给两个矩形分别再切几刀。

  搜索是基本功啊。

// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int MAX=12;
int n,m,k,w[MAX][MAX],s[MAX][MAX];
double ave,f[MAX][MAX][MAX][MAX][MAX];
double cal(double x) { return x*x; }
double dfs(int a,int b,int c,int d,int p) {
	double &g=f[a][b][c][d][p];
	if(g!=-1) return g;
	if(!p) return g=cal(s[c][d]-s[a-1][d]-s[c][b-1]+s[a-1][b-1]-ave);
	g=1e9;
	for(int i=a;i<c;i++) 
		for(int j=0;j<p;j++)
			g=min(g,dfs(a,b,i,d,j)+dfs(i+1,b,c,d,p-j-1));
	for(int i=b;i<d;i++) 
		for(int j=0;j<p;j++) 
			g=min(g,dfs(a,b,c,i,j)+dfs(a,i+1,c,d,p-j-1));
	return g;
}
int main() {
	freopen("separation.in","r",stdin);
	freopen("separation.out","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	for(int a=1;a<=n;a++) for(int b=1;b<=m;b++)
		for(int c=a;c<=n;c++) for(int d=b;d<=m;d++)
			for(int e=0;e<k;e++) f[a][b][c][d][e]=-1;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&w[i][j]);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) 
		s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+w[i][j];
	ave=s[n][m]*1.0/k;
	dfs(1,1,n,m,k-1);
	printf("%.2lf\n",sqrt(f[1][1][n][m][k-1]/k));
	return 0;
}

 

posted @ 2018-04-11 15:22  qjs12  阅读(109)  评论(0编辑  收藏  举报