POJ 1191 棋盘分割

来源:互联网 发布:复杂网络节点中心性 编辑:程序博客网 时间:2024/05/16 08:31

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


均方差公式比较复杂,先将其变形

S^2 = 1/n∑(Xi - X)^2

= 1/n(n*X^2 + ∑Xi^2 - 2*X∑Xi)

= 1/n∑Xi^2 - X^2;

X表示均值

由于均值是一定的(它等于方格里的数和除以n),所以只需要让每个矩形的总分的平方和尽量小

对于左上角(x1,y1),右下角(x2,y2)的正方形,设它的总和为S[x1,y1,x2,y2]

切割K次后得到的K+1块矩形的总分平方和最小值为f[k,x1,y1,x2,y2]

则它可以横着切,也可以竖着切,然后选一块切(这里用到了递归!)
如(横着切)

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

本题要用到记忆化搜索,可以先全部赋值为-1


#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;int n,s[9][9],f[16][9][9][9][9];int count(int x1,int y1,int x2,int y2)//求区域平方和 {    int tmp=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];    return tmp*tmp;}int dp(int k,int x1,int y1,int x2,int y2)//需要形成k个矩形 {    if(f[k][x1][y1][x2][y2]>=0)        return f[k][x1][y1][x2][y2];    if(k==1)        return f[k][x1][y1][x2][y2]=count(x1,y1,x2,y2);    f[k][x1][y1][x2][y2]=1e9;    for(int i=x1;i<=x2-1;i++)//横着切         f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],min(dp(1,x1,y1,i,y2)+dp(k-1,i+1,y1,x2,y2),dp(k-1,x1,y1,i,y2)+dp(1,i+1,y1,x2,y2)));    for(int i=y1;i<=y2-1;i++)        f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],min(dp(1,x1,y1,x2,i)+dp(k-1,x1,i+1,x2,y2),dp(k-1,x1,y1,x2,i)+dp(1,x1,i+1,x2,y2)));    return f[k][x1][y1][x2][y2];}int main(){    scanf("%d",&n);    for(int i=1;i<=8;i++)        for(int j=1;j<=8;j++)        {            int x;            scanf("%d",&x);            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+x;        }    memset(f,-1,sizeof(f));    printf("%.3f\n",sqrt((double)dp(n,1,1,8,8)/n-(double)s[8][8]*s[8][8]/(n*n)));    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 胸经过整容后变得胸闷怎么办? 网瘾高中不学习怎么办 犯罪人逃到美国怎么办 10岁儿童偏胖怎么办 土地面积与实际面积不符怎么办 军转进省直单位双选失败怎么办 房改房楼龄到了70年怎么办 商品房房改房到70年后怎么办 公务员未享受房改政策怎么办 两套房改房违规怎么办 法院保全的物品在我家怎么办 西瓜视频答题结束了钱没提现怎么办 诚信答题密码忘了怎么办 我未成年杀了人怎么办 错过了网课考试怎么办? 2018广东省普法考试0分怎么办 小孩错过了小升初的考试怎么办 错过了自主招生考试怎么办? 科目一考试错过了时间怎么办 中学生网瘾怎么办济南远大认真 u盘安装不了系统怎么办 对敏感脆弱的青春期孩子怎么办? 脸变得很交黑怎么办 玩手机长痘痘了怎么办 青少年左侧后背突发疼痛怎么办 纵欲过度导致青少年白发怎么办 20岁了不想长大怎么办 网吧老板跑路了怎么办 网吧玩地下城卡怎么办 个人公积金封存之前厂子欠费怎么办 学生欠了2万块怎么办 玉米去完库存量cool怎么办 幸福蓝海电子券过期怎么办 幸福蓝海国际影城会员怎么办 幸福蓝海会员卡过期了怎么办 电机线圈处于平衡位置怎么办 混联电路求电功率最小怎么办 电脑超出工作频率范围怎么办 手机红外线感应器坏了怎么办 我的世界左右慢怎么办 发电机自动启停装置故障怎么办