[HAOI2007] 分割矩陣

添雅發表於2018-12-26

顯然,最終的平均值不變。
這樣,我們設f[w,a,b,c,d]為在矩形[a~c,b~d]中割了w刀的根號內分子和。

那麼,狀態轉移有f[w,a,b,c,d] = min
f[p,a,b,k,d]+f[w-p-1,k+1,b,c,d]
f[p,a,b,c,k]+f[w-p-1,a,k+1,c,d]

初始化為 f[0,a,b,c,c,d]=sqr (sum[a~c,b~d] – ave)

階段是割的次數。dp就好了。
答案最終除以t再開根號。

附錄:
均方差,通常指標準差 ,表示式為
[
sqrt{frac{sum_{i=1}^N (x_i-ar x)}{N}}
]

#include <bits/stdc++.h>
using namespace std;

int n,m,t;
double s[11][11],ave;
double f[30][11][11][11][11]; 

double sum(int a,int b,int c,int d) {
    return s[c][d]-s[a-1][d]-s[c][b-1]+s[a-1][b-1];
}
double sqr(double x) {
    return x*x;
}
void upmin(double&x,const double&y) {
    if(y<x) x=y;
}

int main() {
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1; i<=n; ++i) {
        for(int j=1; j<=m; ++j) {
            scanf("%lf",&s[i][j]);
            ave+=s[i][j]; 
            s[i][j]=s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        }
    }
    ave/=t;
    memset(f,0x7f,sizeof f);
    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) {
                    f[0][a][b][c][d]=sqr(sum(a,b,c,d)-ave);
                }
            }
        }
    }
    for(int w=1; w<t; ++w) {
        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 p=0; p<w; ++p) {
                            for(int k=a; k<c; ++k) {
                                upmin(f[w][a][b][c][d],f[p][a][b][k][d]+f[w-p-1][k+1][b][c][d]);
                            }
                            for(int k=b; k<d; ++k) {
                                upmin(f[w][a][b][c][d],f[p][a][b][c][k]+f[w-p-1][a][k+1][c][d]);
                            }
                        }
                    }
                }
            }
        }   
    }  //真是令人智熄
    printf("%.2f
",sqrt(f[t-1][1][1][n][m]/t));
    return 0;
}

相關文章