eoj1096 dp

Description

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

noi


题目:EOJ1096

 

题目分析:

均方差用方差的根号表示,方差最小时,均方差最小,化简可得方差公式为∑Xi^2/n-x^2,即求Xi平方和的最小值。可以用递归的思想求解,将一个矩形分为k个,枚举出所有将此矩形分成两部分的方法,再将这两部分矩形中,其中一个分成一个(既不用再分),将另一个矩形分为k-1个。为提高效率,采用记忆化搜索。用dp(x1,y1.x2,y2,k)表示将左上角和右下角坐标分别为(x1,y1),(x2,y2)的一个矩形分为k块的Xi的平方和的最小值。注意当x1=x2时表示矩形长度为1,y1=y2时同理。

 

AC代码:
#include<iostream>

#include <cstdio>

#include <cmath>

#include <cstring>

 

using namespace std;

 

int dp[9][9][9][9][16];

int map[10][10]={};

 

 

int f(int x1,int y1,int x2,int y2,int k)

{

   if(dp[x1][y1][x2][y2][k]>=0 || k==1 || (x2==x1 && y2==y1))

        returndp[x1][y1][x2][y2][k];

    int i;

    intans1=210000000,ans2=2100000000;

    for(i=x1;i<x2;++i)

    {

        ans1=min(ans1,min(dp[x1][y1][i][y2][1]+f(i+1,y1,x2,y2,k-1),

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

    }

    for(i=y1;i<y2;++i)

    {

        ans2=min(ans2,min(dp[x1][y1][x2][i][1]+f(x1,i+1,x2,y2,k-1),

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

    }

   dp[x1][y1][x2][y2][k]=min(ans1,ans2);

    return dp[x1][y1][x2][y2][k];

}

 

int main()

{

    int n,all=0;

    cin>>n;

    int i,j,x1,x2,y1,y2;

    for(i=1;i<9;++i)

        for(j=1;j<9;++j)

        {

            cin>>map[i][j];

            all+=map[i][j];

        }

    memset(dp,-1,sizeof(dp));

    for(x1=1;x1<9;++x1)

        for(x2=x1;x2<9;++x2)

           for(y1=1;y1<9;++y1)

               for(y2=y1;y2<9;++y2)

                    {

                        int t=0;

                       for(i=x1;i<=x2;++i)

                           for(j=y1;j<=y2;++j)

                               t+=map[i][j];

                       dp[x1][y1][x2][y2][1]=t*t;

                    }

 

    doublea=1.0*f(1,1,8,8,n),b=1.0*all/n;

    //printf("%f   %f\n",a,b);

   printf("%.3f\n",sqrt( a/n-b*b ));

    return 0;

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值