NOI99棋盘分割(题目+分析+题解)

NOI99:棋盘分割

这是一个很让人头疼的题目,所以说,我要细讲.

有的时候我会一带而过:yum:

我们还是先浏览一下题目

棋盘分割

Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 15913Accepted: 5672

Description

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

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。  均方差 σ= σ = ni=1(xix¯¯¯)2n ∑ i = 1 n ( x i − x ¯ ) 2 n ,其中平均值 x¯¯¯=ni=1xin x ¯ = ∑ i = 1 n x i n , xi x i 为第i块矩形棋盘的总分。

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

Input

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

Output

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

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 99


这次主要讲的还是深搜(DP)来做的。

我总结了,只要细心,这道题保证不错!

这道题目主要抓的是最小值,然后,切割后记录坐标放到一个数组里。

这道题目看起来的确是很吓人,但是,我们已经掌握了dfs的子函数的用法了,那就是小菜一碟喽:happy:!!!

我们还是主要是运用着sqrt的开方来得出一些我们得不出的数字。

:joy:


Begin! B e g i n !


写f数组

f数组是一个很重要的数组,它可以给我们做很多关于’刀’的事

先写横的

我们需要定义一个电脑中最大的数min

min1=0x7fffffff;

然后在横的基础上写个循环,直接从x1到x2-1的循环,因为,我们需要一些空间来切割。

for(int i=x1;i<=x2-1;++i){
}

切上留下

我们需要理解一个问题:

? 上 变 成 了 什 么 , 下 变 成 了 什 么 ?

上面是直接从:(x1,y1)→(x,y2)

下面是直接从(x+1,y1)→(x2,y2)

由此,我们可以这样写一个判断(if)

if(x-x1+y2-y1>=d-1){
            if(data[d-1][x1][y1][x][y2]==-1) f(d-1,x1,y1,x,y2);
            min1x=data[d-1][x1][y1][x][y2]+sqr(f2(x+1,y1,x2,y2));
        } 

把这个嵌套在循环里:

for(int i=x1;i<=x2-1;++i){
        //切上留下 
        //上(x1,y1)→(x,y2)
        //下(x+1,y1)→(x2,y2)
        if(x-x1+y2-y1>=d-1){
            if(data[d-1][x1][y1][x][y2]==-1) f(d-1,x1,y1,x,y2);
            min1x=data[d-1][x1][y1][x][y2]+sqr(f2(x+1,y1,x2,y2));
        } 
    }

由此,可以看出这个循环嵌套是奔着f来的

主程序

我们先读入一个n

scanf("%d",&n);

然后,我们读入8组横行测试数据。

for(int i=1;i<=8;++i){
        for(int j=1;j<=8;++j){
            scanf("%d",&map[i][j]);
        }
    }

然后,我们开始复环

我们要复环x1,x2,x3,xx

x1=f2(1,1,8,3);
x2=f2(1,4,4,8);
x3=f2(5,4,8,8);
xx=f2(1,1,8,8);

然后,把y磨掉

y=1.0*xx/n;

……

ans1=0;
double ans1=sqrt((x1-y)*(x1-y)+(x2-y)*(x2-y)+(x3-y)*(x3-y)); 
printf("%3ld",ans1);

撒花完结!!!:call_me_hand:

By Alex_Savege(AlexTEAM)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值