题目传送门:http://poj.org/problem?id=1191

棋盘分割

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 16150   Accepted: 5768

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

 

题意概括:

中文题,不容小觑。

解题思路:

一、DFS搜索,每次分割棋盘可以选择两个方向 横切(改变Y的范围) 或者 竖切(改变X的范围);选择切割方向之后需要选择舍弃两部分之中的其中一部分,继续DFS另一部分。
二、但单纯的搜索太慢,我们可以发现其实是因为有很多子问题重叠,所以不妨用一个四维数组记录每次小矩形的运算结果,数组下标为小矩阵左上角和右下角的坐标。
三、公式化简:
 
AC code:
 ///POJ 1191 棋盘分割 (记忆化搜索经典)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define INF 0x3f3f3f3f
#define ll long long int
#define mod 1000000007
using namespace std; const int MAXN = ;
const int MAXM = ;
double d[MAXN][MAXM][MAXM][MAXM][MAXM];
double record[MAXM][MAXM][MAXM][MAXM];
double mmp[MAXM][MAXM];
double sum, ave;
int N; double get_sum(int x1, int y1, int x2, int y2)
{
if(record[x1][y1][x2][y2]>=) return record[x1][y1][x2][y2];
double re = ;
for(int i = x1; i <= x2; i++)
for(int j = y1; j <= y2; j++)
re+=mmp[i][j];
record[x1][y1][x2][y2] = re*re;
return record[x1][y1][x2][y2];
} double dfs(int x1, int y1, int x2, int y2, int cnt)
{
if(d[cnt][x1][y1][x2][y2]>=) return d[cnt][x1][y1][x2][y2];
if(cnt == N)
{
return get_sum(x1, y1, x2, y2);
}
double min_sum = ;
double tp = ;
for(int i = x1; i < x2; i++)
{
tp = get_sum(x1, y1, i, y2) + dfs(i+, y1, x2, y2, cnt+);
if(min_sum > tp) min_sum = tp;
tp = get_sum(i+, y1, x2, y2) + dfs(x1, y1, i, y2, cnt+);
if(min_sum > tp) min_sum = tp;
}
for(int j = y1; j < y2; j++)
{
tp = get_sum(x1, y1, x2, j) + dfs(x1, j+, x2, y2, cnt+);
if(min_sum > tp) min_sum = tp;
tp = get_sum(x1, j+, x2, y2) + dfs(x1, y1, x2, j, cnt+);
if(min_sum > tp) min_sum = tp;
}
d[cnt][x1][y1][x2][y2] = min_sum;
return min_sum;
} int main()
{
scanf("%d", &N);
memset(d, -, sizeof(d));
memset(record, -, sizeof(record));
for(int i = ; i <= ; i++)
for(int j = ; j <= ; j++)
{
scanf("%lf", &mmp[i][j]);
sum+=mmp[i][j];
}
ave = sum/(N*1.0);
ave*=ave;
double res = dfs(, , , , );
double ans = sqrt(res/N-ave);
printf("%.3f\n", ans);
return ;
}
 
 
 

POJ 1191 棋盘分割 【DFS记忆化搜索经典】的更多相关文章

  1. poj 1191 棋盘分割(dp + 记忆化搜索)

    题目:http://poj.org/problem?id=1191 黑书116页的例题 将方差公式化简之后就是 每一块和的平方 相加/n , 减去平均值的平方. 可以看出来 方差只与 每一块的和的平方 ...

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

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

  3. poj 3249(bfs+dp或者记忆化搜索)

    题目链接:http://poj.org/problem?id=3249 思路:dp[i]表示到点i的最大收益,初始化为-inf,然后从入度为0点开始bfs就可以了,一开始一直TLE,然后优化了好久才4 ...

  4. 不要62 hdu 2089 dfs记忆化搜索

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给你两个数作为一个闭区间的端点,求出该区间中不包含数字4和62的数的个数 思路: 数位dp中 ...

  5. dfs+记忆化搜索,求任意两点之间的最长路径

    C.Coolest Ski Route 题意:n个点,m条边组成的有向图,求任意两点之间的最长路径 dfs记忆化搜索 #include<iostream> #include<stri ...

  6. POJ 2704 Pascal's Travels 【DFS记忆化搜索】

    题目传送门:http://poj.org/problem?id=2704 Pascal's Travels Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  7. POJ 1088 滑雪 DFS 记忆化搜索

    http://poj.org/problem?id=1088 校运会放假继续来水一发^ ^ 不过又要各种复习,功课拉下了许多 QAQ. 还有呀,就是昨天被一个学姐教育了一番,太感谢了,嘻嘻^ ^ 好了 ...

  8. poj1088-滑雪 【dfs 记忆化搜索】

    http://poj.org/problem?id=1088 滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 79806 ...

  9. BZOJ1048:[HAOI2007]分割矩阵(记忆化搜索DP)

    Description 将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个), 这样分割了(n-1)次后,原矩阵被分割成 ...

随机推荐

  1. groovy与javah互相调用

    暂时只找到这几种方法.groovy代码方便灵活.常用来写一些工具.一般都是java加入groovy代码 第一种 java中加入 groovy代码就是 Toy.groovy class Toy{ def ...

  2. 现学现卖】IntelliJ+EmmyLua 开发调试Unity中Xlua

    http://blog.csdn.net/u010019717/article/details/77510066?ref=myread http://blog.csdn.NET/u010019717 ...

  3. 前端测试框架 puppeteer 文档翻译

    puppeteer puppeteer 是一个通过DevTools 协议提供高级API 来控制 chrome,chromium 的 NODE库; puppeteer默认运行在 headless 模式, ...

  4. 对while;do while;for三种循环语句的理解与区分。

    while:先判断表达式的值,在表达式值为真的情况下执行循环语句,直到表达式值为假结束循环: while(循环条件) { 循环体. } do-while:先执行循环体语句一次,再判别表达式的值,在表达 ...

  5. concat、concat_ws、group_concat函数用法

    一.concat()函数可以连接一个或者多个字符串 CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串.如有任何一个参数为NULL ,则返回值为 NULL. select conc ...

  6. mvc中RedirectToAction()如何传参?

    今天在做一个功能的时,使用RedirectToAction()需要从这里传几个参数,从网上查了一下,这样解决.真好. Return RedirectToAction("Index" ...

  7. 2017年9月22日 关于JS数组

    JS数组 JS数组的定义方法 var arr = []; var arr = new Array() JS数组属性 长度 arr.length 遍历数组 索引值:从0开始数 第一种方法 for(var ...

  8. js之strict模式

    JavaScript在设计之初,为了方便初学者学习,并不强制要求用var申明变量.这个设计错误带来了严重的后果:如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量: i = 10 ...

  9. js系列之js简介

    该系列教程都来源于:廖雪峰老师的博客 JavaScript是世界上最流行的脚本语言,因为你在电脑.手机.平板上浏览的所有的网页,以及无数基于HTML5的手机App,交互逻辑都是由JavaScript驱 ...

  10. Java集合篇一:ArrayList

    package com.test.collection; /** * 自定义ArrayList容器 * * 1.实现原理:底层封装数组 * * 2.查询 * LinkList 相较 ArrayList ...