棋盘分割

Time Limit: 1000MS Memory Limit: 10000K

Total Submissions: 13593 Accepted: 4846

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

总结出来状态转移方程,这道题目就好解决了,

状体转移方程

横着切x轴

dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],

dp[0][x1][y1][t][y2]+dp[k-1][t+1][y1][x2][y2]);

dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],

dp[k-1][x1][y1][t][y2]+dp[0][t+1][y1][x2][y2])

竖着切y轴

dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],

dp[0][x1][y1][x2][t]+dp[k-1][x1][t+1][x2][y2]);

dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],

dp[k-1][x1][y1][x2][t]+dp[0][x1][t+1][x2][y2]);

#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h> using namespace std;
#define MAX 99999999
int a[10][10];
double dp[15][10][10][10][10];//一个矩形的两个顶点和切割了几次
int num[10][10];
int res;
double sum(int x1,int y1,int x2,int y2)
{
double ans=(double)(num[x2][y2]-num[x2][y1-1]-num[x1-1][y2]+num[x1-1][y1-1]);
return ans*ans;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(num,0,sizeof(num));
res=0;
for(int i=1;i<=8;i++)
{
for(int j=1;j<=8;j++)
{
scanf("%d",&a[i][j]);
num[i][j]=(num[i-1][j]+num[i][j-1]-num[i-1][j-1]+a[i][j]);
res+=a[i][j];
}
}
//数组初始化
for(int x1=1;x1<=8;x1++)
for(int y1=1;y1<=8;y1++)
for(int x2=x1;x2<=8;x2++)
for(int y2=y1;y2<=8;y2++)
dp[0][x1][y1][x2][y2]=sum(x1,y1,x2,y2);
for(int k=1;k<n;k++)
{
for(int x1=1;x1<=8;x1++)
{
for(int y1=1;y1<=8;y1++)
{
for(int x2=x1;x2<=8;x2++)
{
for(int y2=y1;y2<=8;y2++)
{
dp[k][x1][y1][x2][y2]=MAX;
for(int t=x1;t<x2;t++)
{
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[0][x1][y1][t][y2]+dp[k-1][t+1][y1][x2][y2]);
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[k-1][x1][y1][t][y2]+dp[0][t+1][y1][x2][y2]);
}
for(int t=y1;t<y2;t++)
{
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[0][x1][y1][x2][t]+dp[k-1][x1][t+1][x2][y2]);
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],dp[k-1][x1][y1][x2][t]+dp[0][x1][t+1][x2][y2]);
}
}
}
}
}
} double ans1=dp[n-1][1][1][8][8]*1.0/n-((double)res*1.0/n)*((double)res*1.0/n);
double ans2=sqrt(ans1); printf("%.3f\n",ans2);
}
return 0;
}

再给一个自己写的记忆化搜索的代码

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdlib.h>
#include <stdio.h> using namespace std;
#define MAX 9999999
int dp[15][9][9][9][9];
int a[9][9];
int vis[15][9][9][9][9];
int n;
int ans; int sum(int x1,int y1,int x2,int y2)
{
int res=0;
for(int i=x1;i<=x2;i++)
{
for(int j=y1;j<=y2;j++)
{
res+=a[i][j];
}
}
return res;
}
int dfs(int x1,int y1,int x2,int y2,int n)
{
if(vis[n][x1][y1][x2][y2]!=-1)
return vis[n][x1][y1][x2][y2];
vis[n][x1][y1][x2][y2]=MAX; //横切
if(x1<x2)
{
for(int k=x1;k<x2;k++)
{
vis[n][x1][y1][x2][y2]=min(vis[n][x1][y1][x2][y2],dfs(x1,y1,k,y2,0)+dfs(k+1,y1,x2,y2,n-1));
vis[n][x1][y1][x2][y2]=min(vis[n][x1][y1][x2][y2],dfs(x1,y1,k,y2,n-1)+dfs(k+1,y1,x2,y2,0));
} }
if(y1<y2)
{
for(int k=y1;k<y2;k++)
{
vis[n][x1][y1][x2][y2]=min(vis[n][x1][y1][x2][y2],dfs(x1,y1,x2,k,0)+dfs(x1,k+1,x2,y2,n-1));
vis[n][x1][y1][x2][y2]=min(vis[n][x1][y1][x2][y2],dfs(x1,y1,x2,k,n-1)+dfs(x1,k+1,x2,y2,0));
} } return vis[n][x1][y1][x2][y2];
}
int main()
{
int num;
while(scanf("%d",&n)!=EOF)
{
num=0;
for(int i=1;i<=8;i++)
{
for(int j=1;j<=8;j++)
{
scanf("%d",&a[i][j]);
num+=a[i][j];
}
}
//memset(vis,-1,sizeof(vis));
for(int x1=1;x1<=8;x1++)
for(int y1=1;y1<=8;y1++)
for(int x2=x1;x2<=8;x2++)
for(int y2=y1;y2<=8;y2++)
for(int k=0;k<=n-1;k++)
{
if(k==0)
{
int term=sum(x1,y1,x2,y2);
vis[0][x1][y1][x2][y2]=term*term;
}
else
vis[k][x1][y1][x2][y2]=-1;
} int ans=dfs(1,1,8,8,n-1); double ans1=ans*1.0/n-((double)num*1.0/n)*((double)num*1.0/n);
double ans2=sqrt(ans1);
printf("%.3f\n",ans2); }
}

POJ-1191-棋盘分割(动态规划)的更多相关文章

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

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

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

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

  3. POJ 1191 棋盘分割 【DFS记忆化搜索经典】

    题目传送门:http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

  4. POJ 1191 棋盘分割

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

  5. POJ 1191棋盘分割问题

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

  6. OpenJudge/Poj 1191 棋盘分割

    1.链接地址: http://bailian.openjudge.cn/practice/1191/ http://poj.org/problem?id=1191 2.题目: 总时间限制: 1000m ...

  7. (中等) POJ 1191 棋盘分割,DP。

    Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次 ...

  8. POJ - 1191 棋盘分割 记忆递归 搜索dp+数学

    http://poj.org/problem?id=1191 题意:中文题. 题解: 1.关于切割的模拟,用递归 有这样的递归方程(dp方程):f(n,棋盘)=f(n-1,待割的棋盘)+f(1,割下的 ...

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

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

  10. POJ 1191 棋盘分割(DP)

    题目链接 题意 : 中文题不详述. 思路 : 黑书上116页讲的很详细.不过你需要在之前预处理一下面积,那样的话之后列式子比较方便一些. 先把均方差那个公式变形, 另X表示x的平均值,两边平方得 平均 ...

随机推荐

  1. 为VS code中的项目添加特定的智能提示功能

    当我们的在用vscode开发项目的时候, 如果项目中引用了jquery包, 我们可以下面的方式获得jquery的类型提示 npm install @types/jquery --save-dev 或我 ...

  2. Linux环境下MySQL设置gbk编码

    1 编辑mysql配置文件 vi /etc/my.cnf 2 创建数据库 CREATE DATABASE `XXX` DEFAULT CHARACTER SET gbk COLLATE gbk_chi ...

  3. Linux+Redis实战教程_day03_4、通用redis命令【重点】

    4.通用redis命令[重点] Redis五种数据类型,String,hash,list,set,有序set l keys pattern:获取所有与pattern匹配的key,返回所有与该key匹配 ...

  4. cocos2dx 3.0 scrollview 在android下面背景變綠色了

    在windows上面跑的是OK的,  在android下面跑的時候就變成這樣子了:

  5. Ansible的Playbook的编写

    在Ansible中,将各个模块组合起来成为一个YAML格式的配置文件,这个配置文件叫做Playbook, Playbook和模块的关系类似于shell脚本和Linux命令之间的关系. Playbook ...

  6. html/php/mysql乱码

    1. html通过jquery的ajax传递数据给php. encodeURI("my.php?name=博客园") 2. php接受 urldecode($_GET[" ...

  7. ORACLE学习笔记 translate,REGEXP_replace

    从一串文本中提取数字: select translate('用纸箱包200/箱',REGEXP_replace('用纸箱包200PCS/箱','[0-9]',''),' ')from dual; tr ...

  8. open-falcon之query

    功能 query组件,提供统一的绘图数据查询入口.query组件接收查询请求,根据一致性哈希算法去相应的graph实例查询不同metric的数据,然后汇总拿到的数据,最后统一返回给用户. 配置文件 { ...

  9. thinkphp3.2 判断星期几

    后台 $w=date('w'); $week=array( "=>"星期日", "=>"星期一", "=>&qu ...

  10. read by other session 等待事件。

    今天是2014-01-06,从今天开始,打算春节之前每天学习一个等待事件,今天就记录一下read by other session这个等待事件笔记. 什么是read by other session? ...