pku 1191 棋盘分割 DP / 记忆化搜索
http://poj.org/problem?id=1191
题意:中文省略.
思路:黑说p116有讲解,
主要的状态转移方程为
横着切:
dp[k][x1][y1][x2][y2] = min(dp[k - 1][x1][y1][mid][y2] + dp[1][mid][y1][x2][y2],dp[k - 1][mid][y1][x2][y2] + dp[1][x1][y1][mid][y2]); x1 + 1 <= mid < x2
竖着切:
dp[k][x1][y1][x2][y2] = min(dp[k - 1][x1][y1][x2][mid] + dp[1][x1][mid][x2][y2],dp[k - 1][x1][mid][x2][y2] + dp[1][x1][y1][x2][mid]); y1 + 1<= mid < y2
#include <cmath>
#include <cstdio>
#include <cstring>
#define maxn 17
#define N 8
using namespace std;
const int inf = 99999999;
int dp[maxn][9][9][9][9];
int map[9][9];
int getDP(int k,int x1,int y1,int x2,int y2)
{
int mid;
int ans = inf;
for (mid = x1 + 1; mid < x2; ++mid)
{
ans = min(ans,dp[k - 1][x1][y1][mid][y2] + dp[1][mid][y1][x2][y2]);
ans = min(ans,dp[k - 1][mid][y1][x2][y2] + dp[1][x1][y1][mid][y2]);
}
for (mid = y1 + 1; mid < y2; ++mid)
{
ans = min(ans,dp[k - 1][x1][y1][x2][mid] + dp[1][x1][mid][x2][y2]);
ans = min(ans,dp[k - 1][x1][mid][x2][y2] + dp[1][x1][y1][x2][mid]);
}
return ans;
}
int main()
{
//freopen("d.txt","r",stdin);
int n,i,j,k;
int x1,y1,x2,y2;
scanf("%d",&n);
memset(map,0,sizeof(map));
int sum = 0;
//map存每个矩形的和
for (i = 1; i <= N; ++i)
for (j = 1; j <= N; ++j)
{
scanf("%d",&map[i][j]);
sum += map[i][j];
map[i][j] += map[i][j - 1] + map[i - 1][j] - map[i - 1][j - 1];
}
//出事话dp将所有划分成一个的求出来
memset(dp,0,sizeof(dp));
for (x1 = 0; x1 < N; ++x1)
for (y1 = 0; y1 < N; ++y1)
for (x2 = x1 + 1; x2 <= N; ++x2)
for (y2 = y1 + 1; y2 <= N; ++y2)
{
int tmp = map[x2][y2] - map[x1][y2] - map[x2][y1] + map[x1][y1];
dp[1][x1][y1][x2][y2] = tmp*tmp;
}
//枚举求解
for (k = 2; k <= n; ++k)
for (x1 = 0; x1 < N; ++x1)
for (y1 = 0; y1 < N; ++y1)
for (x2 = x1 + 1; x2 <= N; ++x2)
for (y2 = y1 + 1; y2 <= N; ++y2)
{
dp[k][x1][y1][x2][y2] = getDP(k,x1,y1,x2,y2);
}
double ans = (1.0*dp[n][0][0][8][8])/n - (1.0*sum*sum)/(n*n*1.0);
printf("%.3lf\n",sqrt(ans));
return 0;
记忆化搜索:
这里只要能够推出状态转移方程,其实记忆化搜索就很好写了。
#include <cmath>
#include <cstdio>
#include <cstring>
#define maxn 17
#define N 8
using namespace std;
const int inf = 99999999;
int dp[maxn][9][9][9][9];
int map[9][9];
/*int getDP(int k,int x1,int y1,int x2,int y2)
{
int mid;
int ans = inf;
for (mid = x1 + 1; mid < x2; ++mid)
{
ans = min(ans,dp[k - 1][x1][y1][mid][y2] + dp[1][mid][y1][x2][y2]);
ans = min(ans,dp[k - 1][mid][y1][x2][y2] + dp[1][x1][y1][mid][y2]);
}
for (mid = y1 + 1; mid < y2; ++mid)
{
ans = min(ans,dp[k - 1][x1][y1][x2][mid] + dp[1][x1][mid][x2][y2]);
ans = min(ans,dp[k - 1][x1][mid][x2][y2] + dp[1][x1][y1][x2][mid]);
}
return ans;
}*/
int getS(int x1,int y1,int x2,int y2)
{
return map[x2][y2] - map[x1][y2] - map[x2][y1] + map[x1][y1];
}
int DP(int k,int x1,int y1,int x2,int y2)
{
int mid;
if (dp[k][x1][y1][x2][y2] != 0) return dp[k][x1][y1][x2][y2];//记忆的由来
if (k == 1)//分割到最小取得值
{
int tp = getS(x1,y1,x2,y2);
dp[1][x1][y1][x2][y2] = tp*tp;
return tp*tp;
}
int ans = inf;
//横向切割
for (mid = x1 + 1; mid < x2; ++mid)
{
ans = min(ans,DP(k - 1,x1,y1,mid,y2) + DP(1,mid,y1,x2,y2));
ans = min(ans,DP(k - 1,mid,y1,x2,y2) + DP(1,x1,y1,mid,y2));
}
//纵向切割
for (mid = y1 + 1; mid < y2; ++mid)
{
ans = min(ans,DP(k - 1,x1,y1,x2,mid) + DP(1,x1,mid,x2,y2));
ans = min(ans,DP(k - 1,x1,mid,x2,y2) + DP(1,x1,y1,x2,mid));
}
dp[k][x1][y1][x2][y2] = ans;
return ans;
}
int main()
{
//freopen("d.txt","r",stdin);
int n,i,j;
scanf("%d",&n);
memset(map,0,sizeof(map));
int sum = 0;
//map存每个矩形的和
for (i = 1; i <= N; ++i)
for (j = 1; j <= N; ++j)
{
scanf("%d",&map[i][j]);
sum += map[i][j];
map[i][j] += map[i][j - 1] + map[i - 1][j] - map[i - 1][j - 1];
}
memset(dp,0,sizeof(dp));
int tmp = DP(n,0,0,8,8);
double ans = (1.0*tmp)/n - (sum*sum*1.0)/(n*n*1.0);
printf("%.3lf\n",sqrt(ans));
return 0;
转载于:https://www.cnblogs.com/E-star/archive/2012/08/12/2634248.html
pku 1191 棋盘分割 DP / 记忆化搜索相关推荐
- poj 1191 棋盘分割(记忆化dp+递归)
根据这2个公式可以 得到 O^2 = sum(x1^2 + x2^2 + x3^2 +...xi^2)/n - 平均值^2 所以我们就是要使得总分的平方和尽量小-- 对于一次切割,可以横着切,可以竖着 ...
- NYOJ 87-棋盘分割(记忆化搜索)
棋盘分割 时间限制:1000 ms | 内存限制:65535 KB 难度:6 描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割 ...
- [蓝桥杯][算法提高VIP]Sharing Chocolate(状压dp记忆化搜索)
题目描述 每天,巧克力在它的许多形式上被全世界数百万人分享.它是一个真正普遍的糖果,实际上在世界上每个国家都能得到. 你发现唯一比吃巧克力更好的事情是把它分享给朋友.不幸的是,你的朋友非常挑剔,有着不 ...
- 思维dp ---- Codeforces Round #711 (Div. 2) - C. Planar Reflections[dp/记忆化搜索]
题目链接 题目大意: 就是给你n个平面和一个寿命为k的衰变粒子.开始粒子从左向右飞行,粒子每经过一个平面就会产生一个副本粒子,这个副本粒子比原粒子的寿命少1,即为k-1,并且飞行方向是原粒子的反方向. ...
- BZOJ1415 [Noi2005]聪聪和可可 【SPFA + 期望dp记忆化搜索】
题目 输入格式 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...
- HDU 5001 概率DP || 记忆化搜索
2014 ACM/ICPC Asia Regional Anshan Online 给N个点,M条边组成的图,每一步能够从一个点走到相邻任一点,概率同样,问D步后没走到过每一个点的概率 概率DP 測 ...
- 数位dp 记忆化搜索java_hdu 5787 数位dp,记忆化搜索
题意:求区间[l,r]内有多少个数符合,这个数的任意的相邻k位数(digits),这k个数都两两不相等 l,r范围是1~1e18,k是2~5 思路:数位DP,因为K<=5,我们最多需要保存下来当 ...
- bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)
1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...
- [蓝桥杯][算法提高VIP]金陵十三钗(状压dp记忆化搜索)
题目描述 在电影<金陵十三钗>中有十二个秦淮河的女人要自我牺牲代替十二个女学生去赴日本人的死亡宴会.为了不让日本人发现,自然需要一番乔装打扮.但由于天生材质的原因,每个人和每个人之间的相似 ...
最新文章
- windows链接Linux的pgsql,postgreSQL在CMD里怎么连接
- php 设置http 请求头信息,php设置http头
- IHttpHandler的妙用(2):防盗链!我的资源只有我的用户才能下载
- 183SDP回铃设置步骤
- 一张图看懂H5、混合应用、微信小程序
- 格力公布“酒后模式”手机专利 网友:喝多了可以光明正大不结账了
- 如何使用Dojo的DatePicker控件制作联动日期选择器
- 锋利的Jquery摘要
- centos7更换源
- matlab2c使用c++实现matlab函数系列教程-ones函数
- Flocker 做为后端存储代理 docker volume-driver 支持
- Matlab The Bisection Method
- Jvisualvm简单使用教程
- php fatal 和php error,从PHP Fatal error: Uncaught Error: Class '' not found in php:说起
- MDK各芯片厂家安装支持包下载地址(含Stm32,Nuvoton等)
- python随机生成一个整数n、求s=1+2+3_随机数字生成与数据杜撰—Python、Stata、R和Excel同步实现(附代码)...
- 个人新出的书籍---《云计算网络珠玑》
- PC端微信登录实现流程
- ThinkPad P1 Gen4 是否支持单条4T固态?
- 物联网+Android(SeekBar)、RGB灯控制
热门文章
- JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔
- 计算机专业英语第五版卢川英pdf,《德意志意识形态》中的“现实的个人”及其自由全面发展.pdf...
- datepick二格式 化时间_考研经验分享(三)英语二作文模板
- C# 调用C++写的dll的实现方法
- ACM竞赛学习整理--模拟算法举例POJ1068
- python获取系统时间为字符串_python怎么获取系统当前的时间
- 一篇演讲 By 浙江大学数学系主任刘克峰
- svm涉及的一些概念
- 数据挖掘讲座:我所知道的一点Data Mining
- 【LeetCode】103# 二叉树的锯齿形层次遍历