• 棋盘分割⭐


    题面

    将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,

    这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)

    原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。

    现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。

    请编程对给出的棋盘及n,求出均方差的最小值。

    输入格式

    第1行为一个整数n。

    第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。

    输出格式

    输出最小均方差值(四舍五入精确到小数点后三位)。

    数据范围

    1<n<15
    

    输入样例:

    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
    

    题解

    区间dp无非就是

    1.初始化 单位区间

    2.循环区间大小

    循环区间的位置

    转移

    首先确定dp的状态变量, f[k][i][j][x][j] 把 左上角(i,j)右下角(x,y)这个区间块划的k划分

    然后确定 f[k][i][j][x][y]的属性, 求方差也就是 D(X) = E((X^{2})) - (E^{2})(X) = ( (sum)val[i][j][x][y] / n) - ({sum / n}^{2})

    所以 属性值为 k划分中的每个换分块的(sum) (val^{2})

    然后转移就行了,

    具体的处理和转移见代码

    wa了半天, double(sum / n) 和 double(sum) / n 是不一样的!!!!

    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define sqr(n) (n) * (n)
    using namespace std;
    typedef long long ll;
    
    int n;
    ll s[9][9], a[9][9], f[65][9][9][9][9], sum;
    
    int main()
    {
        cin >> n;
        rep (i, 1, 8) 
            rep (j, 1, 8)
            {
                cin >> a[i][j]; sum += a[i][j];
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
    
                rep (x, 1, i)
                    rep (y, 1, j)
                        f[1][x][y][i][j] = sqr(s[i][j] - s[i][y - 1] - s[x - 1][j] + s[x - 1][y - 1]);  
            }
    
        rep (k, 2, n)
            rep (i, 1, 9)
                rep (j, 1, 9)
                    rep (x, i, 9)
                        rep (y, j, 9)
                        {
                            ll& cur = f[k][i][j][x][y]; cur = 2e18;
                            rep (l, i, x - 1)
                                cur = min(cur, min(f[1][i][j][l][y] + f[k - 1][l + 1][j][x][y], 
                                  f[k - 1][i][j][l][y] + f[1][l + 1][j][x][y]));
                            rep (l, j, y - 1)
                                cur = min(cur, min(f[1][i][j][x][l] + f[k - 1][i][l + 1][x][y], 
                                  f[k - 1][i][j][x][l] + f[1][i][l + 1][x][y]));
                        }
    
        printf("%.3f
    ", sqrt(double(f[n][1][1][8][8]) / n - sqr(double(sum) / n)));
        return 0;
    }
    
  • 相关阅读:
    Android开发之SQLite的使用方法
    【转】如何分析解决Android ANR
    error log
    33层高楼为什么27楼和28楼最贵 次顶层房价高原因揭秘
    Could not allocate CursorWindow size due to error -12 错误解决方法
    过来人讲述买房血泪史:什么样的房子不能碰
    cocos2d-x删除vs2010项目模板
    Lua学习笔记5:类及继承的实现
    Linux vsftpd服务配置具体解释
    Android_Dialog_设置Dialog窗体的大小
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12865279.html
Copyright © 2020-2023  润新知