将方差公式转换 :

  方差:  poj 1191 棋盘分割 公式转换,横纵方向动态规划    均值:  poj 1191 棋盘分割 公式转换,横纵方向动态规划    

  得到:  poj 1191 棋盘分割 公式转换,横纵方向动态规划

 

  我们知道 均值 X 为定值,与如何划分无关, 所以上述公式, 仅与 poj 1191 棋盘分割 公式转换,横纵方向动态规划   有关.

  那么我们可以通过求出最优的 poj 1191 棋盘分割 公式转换,横纵方向动态规划, 即可求出最优 方差值.

  因为对于任意矩形,我们可以通过 其左上角,右下角 坐标来唯一确定,且要保证结果无后效性,我们增加一维切割次数N

  定义状态 DP(N,X1,Y1,X2,Y2) 为将 矩形(X1,Y1,X2,Y2)划分N次 的最小 平方值和

  则根据题目得到    poj 1191 棋盘分割 公式转换,横纵方向动态规划

  对于当前状态 DP(K,X1,Y1,X2,Y2)

  对于 矩形 (X1,Y1,X2,Y2) ,依据题目要求只可在边缘切割,所以我们的切割方案分为两类:

    一,沿着 横坐标 切割,假定切割值为a,则划分为两个小矩形:S1(X1,Y1,A,Y2),S2(A+1,Y1,X2,Y2)        //这里是按点划分,而非按块,A点属于前者,则A+1属于后者

    二,沿着 纵坐标 切割,假定切割值为B,则划分为两个小矩形:S1(X1,Y1,X2,B),S2(X1,B+1,X2,Y2)

  两种情形下的划分后,我们可以从中任选一块继续划分

  所以状态转移方程为:

    DP(K,X1,Y1,X2,Y2)= MIN
    {    

        MIN( DP(K-1,X1,Y1,A,Y2)+S(A+1,Y1,X2,Y2), DP(K-1,A+1,Y1,X2,Y2)+S(X1,Y1,A,Y2) ),     // X1 <= A < X2

        MIN( DP(K-1,X1,Y1,X2,B)+S(X,B+1,X2,Y2),DP(K-1,X1,B+1,X2,Y2)+S(X1,Y1,X2,B))     // Y1 <= B < Y2

    }

  这里的 S(X1,Y1,X2,Y2)指此矩形的权值和的平方

  我们可以通过 O(N*N)预处理出 以(1,1)为左上角顶点的矩形权值和,然后通过简单容斥(S(X2,Y2)-S(X1-1,Y2)-S(X1,Y2-1)+S(X1-1,Y1-1) )

  来 O(1)实现策略。

  总时间复杂度为 O(M^5*N)

解题代码:

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>

const int inf = 0x3fffffff;

int MIN( int a, int b ){ return a < b ? a : b; }
int mp[10][10], s[10][10], dp[15][10][10][10][10];
int n;

int comp( int x1, int y1, int x2, int y2 )
{
    // return the area of (x1,y1,x2,y2)
    int tmp = s[x2][y2]-s[x2][y1-1]-s[x1-1][y2] + s[x1-1][y1-1];
    return (tmp*tmp);
}

int dfs( int k, int x1, int y1, int x2, int y2 )
{
    if( dp[k][x1][y1][x2][y2] != -1 ) return dp[k][x1][y1][x2][y2];
    if( k == 0 ){
        int tmp = comp(x1,y1,x2,y2);
        return (dp[k][x1][y1][x2][y2]=tmp);
    } 

    int res = inf;
    // solve row
    for(int a = x1; a < x2; a++)
    {
        int tmp = MIN( dfs(k-1,x1,y1,a,y2)+comp(a+1,y1,x2,y2), dfs(k-1,a+1,y1,x2,y2)+comp(x1,y1,a,y2) );    
        res = MIN( res, tmp );    
    }
    // solve colomn
    for(int b = y1; b < y2; b++)
    {
        int tmp = MIN( dfs(k-1,x1,y1,x2,b)+comp(x1,b+1,x2,y2), dfs(k-1,x1,b+1,x2,y2)+comp(x1,y1,x2,b) );
        res = MIN( res, tmp );
    }
    return (dp[k][x1][y1][x2][y2]=res);
}
int main()
{

    while( scanf("%d", &n) != EOF)
    {
        int sum = 0;    
        for(int i = 1; i <= 8; i++)
            for(int j = 1; j <= 8; j++)
            {
                scanf("%d", &mp[i][j] );
                sum += mp[i][j];
            }    
        memset(s,0,sizeof(s));    
        memset(dp,0xff,sizeof(dp));    
        // Get the Area S(1,1,x,y)     
        for(int r = 1; r <= 8; r++)
        {
            s[1][r] = s[1][r-1] + mp[1][r];
            s[r][1] = s[r-1][1] + mp[r][1];    
        }    
        for(int r = 2; r <= 8; r++)
            for(int c = 2; c <= 8; c++)
                s[r][c] = s[r-1][c]+s[r][c-1]-s[r-1][c-1] + mp[r][c];    

        int x = dfs( n-1, 1, 1, 8, 8 );
//        printf("x = %d\n", x );
        double ans =  sqrt( 1.*((x*n)-sum*sum)/(n*n) ) ;
        printf("%.3lf\n", ans );
    }
    return 0;
}

 

相关文章: