zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    SVN如何新建用户并分配权限
    Android性能测试工具Emmagee介绍
    Jquery 中的$(this) 和javascript中的this
    Django 的开始之路
    Python 100道题深入理解
    怎么使用jquery判断一个元素是否含有一个指定的类(class)
    windows下面安装Python和pip
    Waves:类Material Design 的圆形波浪(涟漪)点击特效插件
    Python 基础语法(三)
    Python 基础语法(四)
  • 原文地址:https://www.cnblogs.com/chezhongyang/p/7703521.html
Copyright © 2011-2022 走看看