棋盘分割

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. [原]unity3d ios平台内存优化(一)

    关于内存优化,人云亦云 各有己见.本文将通过设置Strpping Level ,减少内存使用. 先看三幅图: 1.没做任何优化,默认选项 2.设置Stripping level 为 Use micro ...

  2. Aspose------导入Excel

    代码: public List<T> ImportExcelToList<T>() { HttpContext context = HttpContext.Current; ) ...

  3. trim思考

    今天发现后台订单商品名称没有的时候出现了HTML代码,然后看了一下源代码(下图是简化版本的) <?php $name = trim('<span style="font-weig ...

  4. WPF路由事件学习(一)

    路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实 ...

  5. 在eclipse中查看android源代码

    自己写了一个类MainAcvitivity extends Activity, 按F12(我把转到定义改成了F12的快捷键),转到Activity的定义,弹出下面这样的界面 就是说没有找到androi ...

  6. 【Android】amr文件时长

    一.文件时长获取 String curAudioFile = “XXX.amr”; MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.s ...

  7. 转载mysql数据库配置优化

    网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...

  8. XSS三重URL编码绕过实例

    遇到一个很奇葩的XSS,我们先来加一个双引号,看看输出: 双引号被转义了,我们对双引号进行URL双重编码,再看一下输出: 依然被转义了,我们再加一层URL编码,即三重url编码,再看一下输出: URL ...

  9. U3D教程宝典之两步实现超实用的XML存档

    两步实现超实用的XML存档 本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝) 脚本下载地址 使用方法非常简单:把GameDataManager和XmlSaver两个脚本添加至工程后(1) ...

  10. C# - 获取类中属性的名称

    用反射控制的,不过获取属性名称的方法,用方法形式获取的,不知道消耗大不大 using System; using System.Collections.Generic; using System.Li ...