[BZOJ1048][HAOI2007]分割矩阵 记忆化搜索

来源:互联网 发布:设备动静密封点数据 编辑:程序博客网 时间:2024/05/18 03:26

观察均方差公式
若将一个区域的代价定于为2,答案为n
动态规划Fx1,y1,x2,y2,t表示图上一个矩形,对这个矩形分割t次得到的代价
当t=1时Fx1,y1,x2,y2,1=(sumave)2
每次枚举一条纵向或者横向的切割线
O(N5)状态,每个状态O(N2)转移,总时间代价O(N7),严重跑不满。

#include <bits/stdc++.h>#define N 12using 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;}