POJ 1191 棋盘分割【区间类DP】

http://poj.org/problem?id=1191

1>根据公式化简:

其中后者是一个已知数。求均方差的最小值就是求出个个棋盘内各数值的平方和最小值。

2>棋盘分割分四种情况:

竖切(左不动),竖切(右不动),横切(上不动),横切(下不动);

3>状态转移方程:

f(i, x1, y1, x2, y2)表示以(x1, y1),(x2, y2)为四边形对角线的棋盘切割成i块的各块值总平方的最小值;

D(x1, y1, x2, y2)表示棋盘的总分

 

                   _____________ 

                   | f(i-1, x1, a+1, x2, y2)+D(x1, y1, x2, a)   [横切(上不动)]

                   | f(i-1, x1,y1, x2, a)+D(x1, a+1, x2, y2)   [横切(下不动)

f(i, x1, y1, x2, y2)=min| f(i-1,b+1, y1, x2, y2)+D(x1, y1, b1, y2)  [竖切(左不动)]

                   | f(i-1, x1, y1, b, y2)+D(b+1, y1, x2, y2)   [竖切(右不动)]

                   ______________

4>其中的a, b是进行枚举的值。先预处理Dx1, y1, x2, y2)

代码如下:

View Code
/**
*  POJ 1191 棋盘分割
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
int a[9][9], F[15][9][9][9][9];
int minx(int a1, int a2, int a3)
{
    int minnum=99999999;
    if(a1<minnum) minnum=a1;
    if(a2<minnum) minnum=a2;
    if(a3<minnum) minnum=a3;
    return minnum;
}
int get(int x1,int y1,int x2,int y2)          //用来计算分割出来块的总分 
{
   return a[x2][y2]-a[x2][y1-1]-a[x1-1][y2]+a[x1-1][y1-1];
}
int main()
{
    int n, i, j, x1, y1, x2, y2, aa, b;
    while(scanf("%d", &n)!=EOF)
    {
        memset(F, 0, sizeof(F));
        memset(a, 0, sizeof(a));
        for(i=1; i<=8; i++)
           for(j=1; j<=8; j++)
           {
               scanf("%d",&a[i][j]);
               a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
           }
        for(i=1; i<=n; i++)
        for(x1=1; x1<=8; x1++)
        for(y1=1; y1<=8; y1++)
        for(x2=1; x2<=8; x2++)
        for(y2=1; y2<=8; y2++)
        {
            if(i==1||x1==x2||y1==y2)
            {
                 F[i][x1][y1][x2][y2]=get(x1, y1, x2, y2)*get(x1, y1, x2, y2);
                 continue;
            }
            int t1=99999999;
            for(aa=y1; aa<y2; aa++)
                t1=minx(t1, F[i-1][x1][aa+1][x2][y2]+get(x1, y1, x2, aa)*get(x1, y1, x2, aa),
                        F[i-1][x1][y1][x2][aa]+get(x1, aa+1, x2, y2)*get(x1, aa+1, x2, y2));
            for(b=x1; b<x2; b++)
                t1=minx(t1, F[i-1][b+1][y1][x2][y2]+get(x1, y1, b, y2)*get(x1, y1, b, y2),
                        F[i-1][x1][y1][b][y2]+get(b+1, y1, x2, y2)*get(b+1, y1, x2, y2));
            F[i][x1][y1][x2][y2]=t1;
        }
        double tt=F[n][1][1][8][8]*1.0/n-pow(a[8][8]*1.0/n, 2.0);
        printf("%.3lf\n", sqrt(tt));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Hilda/p/2939688.html