棋盘分割

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. 转:Hibernate query.list()之卡住问题

    某个函数里面有调用Query的list()方法,然后它有时会出现这种症状: 忽然停住不动,但是也没报异常,就是界面死了. 我的查询差不多是这样: Query q=sessionFactory.open ...

  2. 为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?【转载】

    转载自:http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifyDataSetChanged-does-not-work.html ...

  3. SpringBoot------集成PageHelper分页功能

    添加MyBatis的代码,地址 https://www.cnblogs.com/tianhengblogs/p/9537665.html 修改以下部分: 1.添加MyBatisConfig packa ...

  4. 05-Vim命令合集

    Vim命令合集 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filena ...

  5. ios开发之--使用AFN上传3.1.0上传视频,不走成功回调原因及解决方法

    在测试接口的时候,发现接口称走走了,但是success的回调不走,检查了下代码,发现没有初始化下面两个方法: manage.responseSerializer = [AFHTTPResponseSe ...

  6. ios开发之--多个按钮单选效果

    开发项目时,有很多场景需要用到按钮单选效果,例如充值页面,选择标签页面等,具体实现代码如下: 1,创建 -(UIView *)headerView { CGFloat width = (Kscreen ...

  7. ios开发之NSString用strong还是用copy?

    代码如下: 1,声明 @property(nonatomic,strong)NSString *firstName; @property(nonatomic,copy)NSString *second ...

  8. MySQL存储过程的异常处理

    阅读目录:存储过程的异常处理 定义异常处理 单一异常处理程序 continue exit 多个异常处理程序 关于错误编号和SQLSTATE码 使用3个处理程序 忽略某一异常的处理 异常处理的命名 异常 ...

  9. MySQL开发面试题

    ……继上一篇MySQL的开发总结之后,适当的练习还是很有必要的…… SQL语法多变,不敢保证唯一,也不敢保证全对,如果错误欢迎指出,即刻修改. 一.现有表结构如下图 TABLENAME:afinfo ...

  10. MDK972-EK开发板裸调试设置和裸机程序烧写(转)

    硬件平台:MDK972-EK开发板编译调试软件:KEIL uVision4仿真工具:JLINK V7/V8   本例子从串口输出信息,如图:       KEIL uVision4调试设置如图所示: ...