zoukankan      html  css  js  c++  java
  • [bzoj1048] [HAOI2007]分割矩阵

    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
    

    Solution

    首先要知道均方差是什么东西,反正我是公式没记全然后被坑了好久。。

    对于一组数据(a_i),设其平均值为(mu),那么均方差(sigma)为:

    [sigma=sqrt{dfrac{sum_{i=1}^{n}(a_i-mu)^2}{n}} ]

    然后直接爆搜就好了。。。总状态不多,要加个记忆化保证复杂度。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    
    #define lf double
    #define sqr(x) ((x)*(x))
    
    lf f[11][11][11][11][11],aver,s[11][11];
    int n,m;
    
    lf dfs(int a,int b,int c,int d,int k) {
    	lf &res=f[a][b][c][d][k];
    	if(res!=-1.0) return res;
    	if(k==0) return res=sqr((lf)s[c][d]-s[a-1][d]-s[c][b-1]+s[a-1][b-1]-aver);
    	res=1e9;
    	for(int i=a+1;i<=c;i++)
    		for(int j=0;j<k;j++) 
    			res=min(res,dfs(a,b,i-1,d,j)+dfs(i,b,c,d,k-j-1));
    	for(int i=b+1;i<=d;i++)
    		for(int j=0;j<k;j++)
    			res=min(res,dfs(a,b,c,i-1,j)+dfs(a,i,c,d,k-j-1));
    	return res;
    }
    
    #define FOR(i) for(int i=0;i<=10;i++) 
    
    int main() {
    	int k;read(n),read(m),read(k);
    	for(int i=1;i<=n;i++)
    		for(int j=1,x;j<=m;j++)
    			read(x),s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+(lf)x;
    	aver=s[n][m]/(lf)k;
    	FOR(a) FOR(b) FOR(c) FOR(d) FOR(e) f[a][b][c][d][e]=-1;
    	printf("%.2lf
    ",sqrt(dfs(1,1,n,m,k-1)/(lf)k));
    	return 0;
    }
    
  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    剑指offer-栈的压入、弹出序列
    剑指offer-包含min函数的栈
    图-Dijkster最短路径
    剑指offer-顺时针打印矩阵
    二叉树的镜像
    剑指offer-树的子结构
  • 原文地址:https://www.cnblogs.com/hbyer/p/10384606.html
Copyright © 2011-2022 走看看