观察均方差公式
若将一个区域的代价定于为
(该区域的和−平均数)2
,答案为
代价的和n−−−−−√
动态规划
Fx1,y1,x2,y2,t
表示图上一个矩形,对这个矩形分割
t
次得到的代价
当t=1时
每次枚举一条纵向或者横向的切割线
O(N5)
状态,每个状态
O(N2)
转移,总时间代价
O(N7)
,严重跑不满。
#include <bits/stdc++.h>
#define N 12
using namespace std;
typedef double db;
const db INF = 1e9;
int n,a,b;
int mp[N][N],sum[N][N];
db ave,dp[N][N][N][N][N];
bool vis[N][N][N][N][N];
inline db qp(db x) {return x*x;}
int gs(int x1,int y1,int x2,int y2) {
return sum[x2][y2] - sum[x2][y1-1] - sum[x1-1][y2] + sum[x1-1][y1-1];
}
inline int rd() {
int x=0,f=1;char ch=getchar();
while (ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
db F(int x1,int y1,int x2,int y2,int t) {
if (t == 1)
return qp( (db)gs(x1,y1,x2,y2) - ave );
if (vis[x1][y1][x2][y2][t]) return dp[x1][y1][x2][y2][t];
db ret = INF;
for (int i=x1;i+1<=x2;i++)
for (int p=1;p<=t-1;p++)
ret = min(ret, F(x1,y1,i,y2,p) + F(i+1,y1,x2,y2,t-p) );
for (int i=y1;i+1<=y2;i++)
for (int p=1;p<=t-1;p++)
ret = min(ret, F(x1,y1,x2,i,p) + F(x1,i+1,x2,y2,t-p) );
vis[x1][y1][x2][y2][t] = 1;
return dp[x1][y1][x2][y2][t] = ret;
}
int main() {
a = rd(), b = rd(), n = rd();
for (int i=1;i<=a;i++)
for (int j=1;j<=b;j++) mp[i][j] = rd();
for (int i=1;i<=a;i++)
for (int j=1;j<=b;j++)
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + mp[i][j];
ave = (db)sum[a][b] / (db)n;
db ans = F(1,1,a,b,n);
printf("%.2lf\n",sqrt(ans/(db)n));
return 0;
}