棋盘分割

Posted 【對策局】

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了棋盘分割相关的知识,希望对你有一定的参考价值。

【题目描述】
 将一个8×8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部 分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩 下的矩形棋盘共有 n 块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行) 

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
请编程对给出的棋盘及 n,求出方差的最小值。

【输入描述】
第 1 行为一个整数 n(1<n<15)。
第 2 行至第 9 行每行为 8 个小于 100 的非负整数,表示棋盘上相应格子的分 值。每行相邻两数之间用一个空格分隔。

【输出描述】
仅一个数,为方差(四舍五入精确到小数点后三位)。

【样例输入】
3

1 1 1 1 1 1 1 3

1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 0

1 1 1 1 1 1 0 3

【样例输出】
1.633

源代码:

#include<cmath>
#include<iostream>
#include<iomanip> //包含【setprecision()】、【fixed】,用于四舍五入保留小数。
#define INF 1000000000 //定义极大值。
using namespace std;
double n,num(0),ans,i[9][9]={0},sum[9][9]={0},f[16][9][9][9][9]; //皆为double类型,方便下面的计算。
int main()
{
    cin>>n; //cin输入流。
    int m=n; //作为int类型数组标志变量。
    for (int a=1;a<=8;a++)
      for (int b=1;b<=8;b++)
      {
        cin>>i[a][b];
          num+=i[a][b]; //总和。
          sum[a][b]=sum[a][b-1]+sum[a-1][b]-sum[a-1][b-1]+i[a][b]; //计算[1][1][a][b]的矩形区间和。
      }
    for (int a=1;a<=8;a++)
      for (int b=1;b<=8;b++)
        for (int c=a;c<=8;c++)
          for (int d=b;d<=8;d++)
          {
              double t;
            t=sum[c][d]-sum[c][b-1]-sum[a-1][d]+sum[a-1][b-1];
            f[0][a][b][c][d]=t*t; //初始化f[切数][x1][y1][x2][y2]数组。
          }
    for (int k=1;k<n;k++) //切了多少次。
      for (int a=1;a<=8;a++)
        for (int b=1;b<=8;b++)
          for (int c=a;c<=8;c++)
            for (int d=b;d<=8;d++)
            {
                f[k][a][b][c][d]=INF; //初始化。
                for (int t=a;t<c;t++) //横切。
                {
                    f[k][a][b][c][d]=min(f[k][a][b][c][d],f[0][a][b][t][d]+f[k-1][t+1][b][c][d]);
                    f[k][a][b][c][d]=min(f[k][a][b][c][d],f[0][t+1][b][c][d]+f[k-1][a][b][t][d]);
                }
                for (int t=b;t<d;t++) //纵切。
                {
                    f[k][a][b][c][d]=min(f[k][a][b][c][d],f[0][a][b][c][t]+f[k-1][a][t+1][c][d]);
                    f[k][a][b][c][d]=min(f[k][a][b][c][d],f[0][a][t+1][c][d]+f[k-1][a][b][c][t]);
                }
            }
    ans=f[m-1][1][1][8][8]/n-(num/n)*(num/n); //切的次数=矩形个数-1。
    cout<<setprecision(3)<<fixed<<sqrt(ans); //亟待学习。
    return 0;
}

以上是关于棋盘分割的主要内容,如果未能解决你的问题,请参考以下文章

POJ百炼——1191棋盘分割

POJ 1191 棋盘分割(DP)

DP专题——棋盘分割

#RANK_3 1191:棋盘分割

POJ1991 NOI1999棋盘分割

POJ 1191 棋盘分割(区间DP)题解