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[][],dp[][][][][],s[][][][];
int add(int x1,int y1,int x2,int y2)
{
int tmp=;
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-,x1,y1,i,y2),t2=dfs(k-,i+,y1,x2,y2);
int t=min(t1+s[i+][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-,x1,y1,x2,i),t2=dfs(k-,x1,i+,x2,y2);
int t=min(t1+s[x1][i+][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=;i<=;i++)
for(int j=;j<=;j++)
scanf("%d",&a[i][j]);
for(int k=;k<=n;k++)
for(int x1=;x1<=;x1++)
for(int y1=;y1<=;y1++)
for(int x2=;x2<=;x2++)
for(int y2=;y2<=;y2++)
dp[k][x1][y1][x2][y2]=INF;
for(int x1=;x1<=;x1++)
for(int y1=;y1<=;y1++)
for(int x2=;x2<=;x2++)
for(int y2=;y2<=;y2++)
{
int tmp=add(x1,x2,y1,y2);
dp[][x1][x2][y1][y2]=s[x1][x2][y1][y2]=tmp*tmp;
}
int tmp=dfs(n,,,,);
int px=add(,,,);
double t=((double) (px) / n )*((double) (px) / n );
double r= (double) (tmp) / n;
printf("%.3lf",sqrt(r-t));
}

[NOI1999] 棋盘分割的更多相关文章

  1. [NOI1999] 棋盘分割(推式子+dp)

    http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 156 ...

  2. POJ1991 NOI1999棋盘分割

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15581   Accepted: 5534 Description ...

  3. POJ 1191 棋盘分割

    棋盘分割 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11213 Accepted: 3951 Description 将一个 ...

  4. poj 1191 棋盘分割 动态规划

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11457   Accepted: 4032 Description ...

  5. NOI 193棋盘分割.cpp

    193:棋盘分割 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分 ...

  6. HDU 2517 / POJ 1191 棋盘分割 区间DP / 记忆化搜索

    题目链接: 黑书 P116 HDU 2157 棋盘分割 POJ 1191 棋盘分割 分析:  枚举所有可能的切割方法. 但如果用递归的方法要加上记忆搜索, 不能会超时... 代码: #include& ...

  7. POJ 1191棋盘分割问题

    棋盘分割问题 题目大意,将一个棋盘分割成k-1个矩形,每个矩形都对应一个权值,让所有的权值最小求分法 很像区间DP,但是也不能说就是 我们只要想好了一个怎么变成两个,剩下的就好了,但是怎么变,就是变化 ...

  8. 洛谷 P1436 棋盘分割 解题报告

    P1436 棋盘分割 题目描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的两部分中的任意一块继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共 ...

  9. poj1191 棋盘分割【区间DP】【记忆化搜索】

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description ...

随机推荐

  1. Leetcode题库——15.三数之和

    @author: ZZQ @software: PyCharm @file: threeSum.py @time: 2018/10/6 19:47 说明:给定一个包含 n 个整数的数组 nums,判断 ...

  2. 团队作业4——第一次项目冲刺(Alpha版本)2017.11.16

    1.当天站立式会议照片 本次会议在5号公寓3楼召开,本次会议内容:①:熟悉每个人想做的模块.②:根据老师的要求将项目划分成一系列小任务.③:在上次会议内容完成的基础上增加新的任务. 2.每个人的工作 ...

  3. Java集合技巧

    集合的一些技巧:   需要唯一吗? 需要:Set 需要制定顺序:  需要: TreeSet 不需要:HashSet 但是想要一个和存储一致的顺序(有序):LinkedHashSet 不需要:List ...

  4. JDBC连接数据库代码和步骤

    JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序  在连接数据库之前,首先要加载想要连接的数据库的驱动,这通过java.lang.Class类的静态方法 ...

  5. javascript 组件化(转载)

    这边只是很简陋的实现了类的继承机制.如果对类的实现有兴趣可以参考我另一篇文章javascript oo实现 我们看下使用方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

  6. 配置高可用集群(实验) corosyne+pacemaker

    环境准备: 一准备三个虚拟机,把/etc/hosts/文件配置好                              192.168.43.9 node0                     ...

  7. Alpha阶段敏捷冲刺④

    1.提供当天站立式会议照片一张. 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 改善界面设计 今天计划完成的工作. 数据库和程序的连接 后端框架的继 ...

  8. PHP 官方发行版扩展下载地址

    PHP扩展下载 稳定发行版资源下载地址: https://windows.php.net/downloads/pecl/releases/ 常用扩展: 持续更新中 ... igbinary序列化/反序 ...

  9. vue 组件 模板中根数据绑定需要指明路径并通信父

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>T ...

  10. Read N Characters Given Read4

    The API: int read4(char *buf) reads 4 characters at a time from a file. The return value is the actu ...