• [NOI1999] 棋盘分割


    COGS 100. [NOI1999] 棋盘分割

    http://www.cogs.pro/cogs/problem/problem.php?pid=100

    ★★   输入文件:division.in   输出文件:division.out   简单对比
    时间限制:1 s   内存限制:128 MB

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

        原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成 n 块矩形棋盘,并使各矩形棋盘总分的均方差最小。
    均方差 ,其中平均值 x i 为第 i 块矩形棋盘的分。
    请编程对给出的棋盘及 n ,求出 的最小值。
     
    【输入格式】
    第 1 行为一个整数 n(1<n<9) 。<="" div="">

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

    【输出格式】
       
    仅一个数,为 (四舍五入精确到小数点后三位)。
    【输入样例】
    输入文件名:division.in

    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
    输出文件名:division.out
    1.633
    注意合法的切割方案是指 切了一刀后,选其中一块继续切,另一块不能再切
    首先将均方差公式变形
     
    第三个等号到第四个等号的变换:
     
    平均值固定不变,所以只需最小化每个矩形总分的平方和
    dp[k][x1][x2][y1][y2] 矩形左上角标号为(x1,y2) ,右上角标号为(x2,y2),分为k个矩形 所得到的最小平方和
    初始化:dp 极大值
    预处理:s[x1][x2][y1][y2]   矩形左上角标号为(x1,y2) ,右上角标号为(x2,y2)内所有数和的平方
              dp[1][x1][x2][y1][y2]=s[x1][x2][y1][y2] (相当于一刀也不切的情况)
    状态转移:dp[k][x1][y1][x2][y2]=min(
                 dp[k-1][x1][y1][x][y2]+s[x+1][y1][x2][y2]) //横着切,取上面一部分继续切
                 dp[k-1][x+1][y1][x2][y2]+s[x1][y1][x][y2]//横着切,取下面一部分继续切
                 dp[k-1][x1][y1][x2][y]+s[x1][y+1][x2][y2]//竖着切,取左边一部分继续切 
                 dp[k-1][x1][y+1][x2][y2]+s[x1][y1][x2][y] //竖着切,取右边一部分继续切
    )
    转移过程可用记忆化搜索实现
     
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define INF 1e9
    using namespace std;
    int n,a[9][9],dp[16][9][9][9][9],s[9][9][9][9];
    int add(int x1,int y1,int x2,int y2)
    {
        int tmp=0;
        for(int i=x1;i<=x2;i++)
         for(int j=y1;j<=y2;j++)
          tmp+=a[i][j];
        return tmp;
    }
    int dfs(int k,int x1,int y1,int x2,int y2)
    {
        if(dp[k][x1][y1][x2][y2]!=INF) return dp[k][x1][y1][x2][y2];
        if(x2>x1)
        {
            for(int i=x1;i<x2;i++)
            {
                int t1=dfs(k-1,x1,y1,i,y2),t2=dfs(k-1,i+1,y1,x2,y2);
                int t=min(t1+s[i+1][y1][x2][y2],t2+s[x1][y1][i][y2]);
                dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],t);
            }
        }
        if(y2>y1)
        {
            for(int i=y1;i<y2;i++)
            {
                int t1=dfs(k-1,x1,y1,x2,i),t2=dfs(k-1,x1,i+1,x2,y2);
                int t=min(t1+s[x1][i+1][x2][y2],t2+s[x1][y1][x2][i]);
                dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],t);
            }
        }
        return dp[k][x1][y1][x2][y2];
    }
    int main()
    {
        /*freopen("division.in","r",stdin);
        freopen("division.out","w",stdout);*/
        scanf("%d",&n);
        for(int i=1;i<=8;i++)
         for(int j=1;j<=8;j++)
          scanf("%d",&a[i][j]);
        for(int k=1;k<=n;k++)
         for(int x1=1;x1<=8;x1++)
         for(int y1=1;y1<=8;y1++)
          for(int x2=1;x2<=8;x2++)
           for(int y2=1;y2<=8;y2++)
            dp[k][x1][y1][x2][y2]=INF;
        for(int x1=1;x1<=8;x1++)
         for(int y1=1;y1<=8;y1++)
          for(int x2=1;x2<=8;x2++)
           for(int y2=1;y2<=8;y2++)
            {
                int tmp=add(x1,x2,y1,y2);
                dp[1][x1][x2][y1][y2]=s[x1][x2][y1][y2]=tmp*tmp;
            }
        int tmp=dfs(n,1,1,8,8);
        int px=add(1,1,8,8);
        double t=((double) (px) / n )*((double) (px) / n );
        double r= (double) (tmp) / n;
        printf("%.3lf",sqrt(r-t));
    }
  • 相关阅读:
    Android(安卓)全套开发资料视频+源码
    腾讯qlv视频转为MP4格式工具
    优酷爱奇艺视频转换为MP4格式工具
    JAVA全套资料含视频源码(持续更新~)
    PPT、Word、Excel模板免费下载
    图片下载
    aspx使用KindEditor副文本框插件出现检测到有潜在危险
    跨域请求
    WEUI滚动加载
    jq复制
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6494512.html
Copyright © 2020-2023  润新知