zoukankan      html  css  js  c++  java
  • poj 1191 棋盘分割 (dp)

    好纠结的一道题啊,一开始 写错了个字母 ,跳了半天,后来脚上去竟然不对,,看了 discuss 里面的 将 所有数据 改为 double 类型 秒过,汗。。。。。。。。。

                                                                                                                                                                                                棋盘分割
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 9151   Accepted: 3215

    Description

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

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

    Input

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

    Output

    仅一个数,为O'(四舍五入精确到小数点后三位)。

    Sample Input

    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

    Sample Output

    1.633

    Source

     
     
     
     

    题解:

    首先将 原式化简 为  ∑xi^2  -  (平均值的平方) 而 平均值是已知的 所以为我们只要球前者就可以

    每一刀,我们只能按 x轴方向切 或 y 方向切

    用  dp[k][x1][y1][x2][y2] 表示 将 以 x1,y1,为左上角,x2,y2,为右下角的矩形 分成 k 分的最小值

    s[x1][y1][x2][y2]  表示   以 x1,y1,为左上角,x2,y2,为右下角的矩形的  平方


    状态转移 为 

    dp[k][x1][y1][x2][y2] = min(dp[k - 1][x1][y1][ i ][y2]) +  s[i+1][y1][x2][y2],    dp[k -  1][x1][y1][i + 1][y2] +    s[x1][y1][i][y2])   (沿 x 轴切)

                                      min(dp[k - 1][x1][y1][ x2][i]) +  s[x1][i + 1][x2][y2],    dp[k -  1][x1][i + 1][x2][y2] +    s[x1][y1][x2][ i ]); 

    代码:

    View Code
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<set>
      7 #include<map>
      8 #include<queue>
      9 #include<vector>
     10 #include<string>
     11 #define Min(a,b) a<b?a:b
     12 #define Max(a,b) a>b?a:b
     13 #define CL(a,num) memset(a,num,sizeof(a));
     14 #define maxn  205
     15 #define eps  1e-6
     16 #define inf 9999999
     17 #define mx 1<<60
     18 
     19 using namespace std;
     20 
     21 double  mat[10][10];
     22 double  dp[20][10][10][10][10];
     23 double s[10][10][10][10] ;
     24 
     25 void init()
     26 {
     27     int i,j,k,l;
     28     double  sum  = 0;
     29 
     30     for(  i = 1;i <= 8;++i)
     31     {
     32         for( j = i; j <= 8 ;++j)
     33         {
     34 
     35             for(k = 1 ; k <= 8; ++k )
     36             {
     37                 sum = 0;
     38 
     39                 for(l = k ; l <= 8 ;++l)
     40                 {
     41                     sum += mat[l][j] - mat[l][i - 1] ;
     42                     s[k][i][l][j] = sum*sum;
     43 
     44                 }
     45 
     46 
     47             }
     48 
     49         }
     50     }
     51 
     52 
     53 }
     54  double  dfs(int k,int x1,int y1,int x2,int y2)
     55 {
     56 
     57      int i;
     58      double tmp ;
     59 
     60 
     61     if(dp[k][x1][y1][x2][y2] >= eps ) return dp[k][x1][y1][x2][y2] ;
     62 
     63     if( k == 1)
     64     {
     65         dp[k][x1][y1][x2][y2] = s[x1][y1][x2][y2] ;
     66          return dp[k][x1][y1][x2][y2] ;
     67     }
     68     else
     69     {
     70         double  ans = inf ;
     71         for(i = x1; i < x2; ++i)
     72         {
     73             tmp = min(dfs(k - 1,x1,y1, i,y2) + s[i+1][y1][x2][y2],dfs(k - 1,i+1,y1,x2,y2) + s[x1][y1][i][y2]);
     74             ans = min(ans,tmp);
     75         }
     76 
     77         for(i = y1; i < y2 ; ++i )
     78         {
     79             tmp = min(dfs(k - 1,x1,y1,x2,i) + s[x1][i + 1][x2][y2],dfs(k - 1,x1,i+1,x2,y2) + s[x1][y1][x2][i]);
     80             ans  = min(ans,tmp);
     81         }
     82 
     83          dp[k][x1][y1][x2][y2] = ans ;
     84 
     85         return dp[k][x1][y1][x2][y2];
     86 
     87 
     88     }
     89 }
     90 int main()
     91 {
     92     int n,i,j;
     93     double  a;
     94     //freopen("data.in","r",stdin);
     95     scanf("%d",&n);
     96 
     97         double cnt = 0;
     98 
     99 
    100         for( i = 1;i <= 8;++i )
    101         {
    102             double sum = 0;
    103             for( j = 1; j <= 8 ;++j)
    104             {
    105                 scanf("%lf",&a);
    106                 sum += a;
    107                 cnt +=a;
    108                 mat[i][j] = sum ;
    109             }
    110         }
    111 
    112 
    113 
    114 
    115 
    116 
    117         init();
    118 
    119          double  k = cnt/(n*1.0);
    120 
    121          double  ans  =  dfs(n,1,1,8,8);
    122 
    123         ans = (ans/(n*1.0)) - k*k ;
    124 
    125         ans = sqrt(ans);
    126         printf("%.3lf\n",ans);
    127 
    128 }
  • 相关阅读:
    Fatal error: Maximum execution time of 30 seconds exceeded in
    常见变量命名规则
    Rust使用国内镜像安装依赖
    flutter使用国内镜像源
    7个每天晚上应该坚持的好习惯
    网络数据传输格式的思考
    Deepin安装 ruby 包管理工具 RVM(适用于 Debian 系列)
    C语言数据类型关键字
    win10 powershell禁止运行脚本解决
    Linux 查看系统相关信息(系统发型版本及内核版本等)
  • 原文地址:https://www.cnblogs.com/acSzz/p/2633325.html
Copyright © 2011-2022 走看看