将 (a imes b) 的数字矩阵沿着数字间的缝隙做分割,分成 (n) 个矩形,每个矩形的分数是矩形内数字和,最小化各矩形分数的均方差。(a,b,n leq 10)
Solution
均方差定义为
[s^2=frac{1}{n}sum_{i}(a_i-avg)^2=frac{1}{n}sum_{i=1}^n (a_i^2-avg^2)=frac{1}{n}sum_{i=1}^n a_i^2-frac{S^2}{n^2}
]
于是就是要最小化 (sum a_i^2)
设 (f[i_1][j_1][i_2][j_2][k]) 表示将矩形 ((i_1,j_1)-(i_2,j_2)) 分割成 (k) 份,(sum a_i^2) 的最小值
转移无非就是枚举分割线,记忆化搜索即可
矩形求和用二维前缀和预处理
时间复杂度 (O(a^3b^3n^2))
#include <bits/stdc++.h>
using namespace std;
const int N = 12;
int a,b,n,s[N][N],f[N][N][N][N][N];
inline int get(int i,int j,int k,int l) {
return s[k][l]-s[i-1][l]-s[k][j-1]+s[i-1][j-1];
}
inline int sh(int &x,int y) {
x=min(x,y);
}
int dfs(int i1,int j1,int i2,int j2,int k) {
if(f[i1][j1][i2][j2][k]<1e9) return f[i1][j1][i2][j2][k];
for(int i=1;i<k;i++) {
for(int j=i1;j<i2;j++) {
sh(f[i1][j1][i2][j2][k],dfs(i1,j1,j,j2,i)+dfs(j+1,j1,i2,j2,k-i));
}
for(int j=j1;j<j2;j++) {
sh(f[i1][j1][i2][j2][k],dfs(i1,j1,i2,j,i)+dfs(i1,j+1,i2,j2,k-i));
}
}
return f[i1][j1][i2][j2][k];
}
signed main() {
ios::sync_with_stdio(false);
cin>>a>>b>>n;
for(int i=1;i<=a;i++) {
for(int j=1;j<=b;j++) {
cin>>s[i][j];
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
}
memset(f,0x3f,sizeof f);
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++) {
f[i][j][k][l][1]=get(i,j,k,l)*get(i,j,k,l);
}
}
}
}
int tmp = dfs(1,1,a,b,n);
double ans = 1.0*tmp/n - 1.0*s[a][b]*s[a][b]/n/n;
printf("%.2lf
",(sqrt(ans)));
}