poj 1191 棋盘分割
2013-06-19 16:35
330 查看
棋盘分割
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
Sample Output
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 10807 | Accepted: 3798 |
将一个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
分析:均方差的公式较复杂,先将其变形为 ,由于平均值是一定的,因此只需要让每个矩形的总分的平方和尽量小。虑左上角坐标为(x1,y1),右下角坐标为(x2,y2)的棋盘,设它的总和为sum[x1,y1,x2,y2]切割k次以后得到k+1块矩形的总分平方和最小值为d[k,x1,y1,x2,y2],则它可以沿着横线切,也可以沿着竖线切,然后选一块继续切(递归).
转移方程为d[k,x1,y1,x2,y2]=min{ * min{d[k-1,x1,y1,a,y2]+s[a+1,y1,x2,y2]^2,d[k-1,a+1,y1,x2,y2]+s[x1,y1,a,y2]^2}(x1<=a<x2)//竖着切,分别取左边的矩形和右边的矩形为剩下部分继续递归,取两者中最小值 * min{d[k-1,x1,y1,x2,b]+s[x1,b+1,x2,y2]^2,d[k-1,x1,b+1,x2,y2]+s[x1,y1,x2,b]^2}(y1<=b<y2)//横着切,分别取上面的矩形和下面的矩形为剩下部分继续递归,取两者中最小值
}
AC代码:
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <algorithm> #include <queue> #include <cmath> #include <vector> #include <cstdlib> #include<iomanip> using namespace std; int d[16][10][10][10][10]; //d[k,x1,y1,x2,y2]表示左上角坐标为(x1,y1),右下角坐标为(x2,y2)的矩形切割k次后得到的总平方和的最小值 int sum[10][10]; //s[i][j]表示左上角坐标为(1,1),右下角坐标为(i,j)的矩形的总分 int m[10][10]; int getsum(int x1,int y1,int x2,int y2) { return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]; } int fun(int k,int x1,int y1,int x2,int y2) //用到记忆化搜索 { int t,min1=100000000; if(d[k][x1][y1][x2][y2]!=-1) return d[k][x1][y1][x2][y2]; if(k==0) { t=getsum(x1,y1,x2,y2); return d[k][x1][y1][x2][y2]=t*t; } for(int a=x1;a<x2;a++) //竖着切,分别取左边的矩形和右边的矩形为剩下部分继续递归,取两者中最小值 { int sum1=getsum(a+1,y1,x2,y2); int sum2=getsum(x1,y1,a,y2); t=min(fun(k-1,x1,y1,a,y2)+sum1*sum1,fun(k-1,a+1,y1,x2,y2)+sum2*sum2); if(t<min1) min1=t; } for(int b=y1;b<y2;b++) //横着切,分别取上面的矩形和下面的矩形为剩下部分继续递归,取两者中最小值 { int sum1=getsum(x1,b+1,x2,y2); int sum2=getsum(x1,y1,x2,b); t=min(fun(k-1,x1,y1,x2,b)+sum1*sum1,fun(k-1,x1,b+1,x2,y2)+sum2*sum2); if(t<min1) min1=t; } return d[k][x1][y1][x2][y2]=min1; } int main() { int n; while(cin>>n) { memset(sum,0,sizeof(sum)); memset(d,-1,sizeof(d)); for(int i=1;i<9;i++) for(int j=1,rowsum=0;j<9;j++) { cin>>m[i][j]; rowsum+=m[i][j]; sum[i][j]+=sum[i-1][j]+rowsum; } double result = n*fun(n-1,1,1,8,8)-sum[8][8]*sum[8][8]; printf("%.3f\n",sqrt(result/(n*n))); } return 0; }
相关文章推荐
- POJ 1191 棋盘分割 DP
- poj 1191 棋盘分割
- [DP+记忆化搜索]poj1191 棋盘分割
- Poj 1191 棋盘分割
- poj-1191-棋盘分割
- POJ1191——棋盘分割
- POJ 1191棋盘分割
- poj&nbsp;1191&nbsp;棋盘分割&nbsp;dp
- POJ 1191 棋盘分割(DP)
- 动态规划 :POJ 1191 棋盘分割
- poj1191-棋盘分割问题
- 经典问题六.【二维的区间dp】棋盘分割 poj 1191
- POJ-1191 棋盘分割 记忆化搜索
- 【POJ 1191】 棋盘分割(DP)
- POJ 1191 棋盘分割
- POJ 1191 棋盘分割
- POJ 1191 棋盘分割 (记忆化搜索)
- (中等) POJ 1191 棋盘分割,DP。
- POJ-1191-棋盘分割(动态规划)
- poj 1191 棋盘分割(DP)