193:棋盘分割

总时间限制: 
1000ms

内存限制: 
65536kB
描述
将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差,其中平均值,xi为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。
输入
第1行为一个整数n(1 < n < 15)。
第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
输出
仅一个数,为O'(四舍五入精确到小数点后三位)。
样例输入
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
样例输出
1.633
来源
Noi 99
 /*
z
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
int n;
int s[][][][],c[][];
int f[][][][][];
int add(int x1,int y1,int x2,int y2 )
{
int w=;
for(int i=x1;i<=x2;i++)
for(int j=y1;j<=y2;j++)
w+=c[i][j];
return w;
}
int dfs(int k,int x1,int y1,int x2,int y2)
{
if(f[k][x1][y1][x2][y2]!=-)
return f[k][x1][y1][x2][y2];
f[k][x1][y1][x2][y2]=INF;
if(x1<x2)//横切
{
for(int x=x1; x<x2; x++)
{
int t1=dfs(k-,x+,y1,x2,y2); //取上面那么递归计算下面
int t2=dfs(k-,x1,y1,x,y2); //去下面那么递归计算上面
int t=min(t1+s[x1][y1][x][y2],t2+s[x+][y1][x2][y2]);
f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],t);
}
}
if(y1<y2)
{
for(int y=y1;y<y2;y++)
{
int t1=dfs(k-,x1,y+,x2,y2) ; //选左边那么递归计算右边
int t2=dfs(k-,x1,y1,x2,y); //选右边那么递归计算左边
int t=min(t1+s[x1][y1][x2][y],t2+s[x1][y+][x2][y2]);
f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],t);
}
}
return f[k][x1][y1][x2][y2];
}
int main()
{
int x1,y1,x2,y2,n;
scanf("%d",&n);
memset(f,-,sizeof(f));
for(int i=;i<=;i++)
for(int j=;j<=;j++)
scanf("%d",&c[i][j]);
for(x1=; x1<=; x1++)
for(x2=x1; x2<=; x2++)
for(y1=; y1<=; y1++)
for(y2=y1; y2<=; y2++)
{
int tmp=add(x1,y1,x2,y2);
f[][x1][y1][x2][y2]=s[x1][y1][x2][y2]=tmp*tmp;
}
dfs(n,,,,);
double X,ans;
X=.*add(,,,);
X=(X/n)*(X/n);
//cout<<f[n][1][1][8][8]<<endl;
ans=sqrt(1.0*f[n][][][][]/n-X);
printf("%.3f\n",ans);
return ;
}
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#define min(a,b) a<b?a:b
#define INF 0x3f3f3f3f
#define N 20
using namespace std;
int dp[N][][][][],s[][][][],c[][];
int add(int x1,int y1,int x2,int y2)
{
int ans=,x,y;
for(x=x1; x<=x2; x++)
for(y=y1; y<=y2; y++)
ans+=c[x][y];
coutMMans;
return ans;
}
int dfs(int k,int x1,int y1,int x2,int y2)
{
if(dp[k][x1][y1][x2][y2]!=-)
return dp[k][x1][y1][x2][y2];
int x,y,t1,t2,t;
dp[k][x1][y1][x2][y2]=INF;
if(x2>x1) //至少有两行才能横着切
{
//1.选上面:dp[k][x1][y1][x2][y2]=s[x1][y1][x][y2]+dp[k-1][x+1][y1][x2][y2];
//2.选下面:dp[k][x1][y1][x2][y2]=s[x+1][y1][x2][y2]+dp[k-1][x1][y1][x][y2];
for(x=x1; x<x2; x++)
{
t1=dfs(k-,x+,y1,x2,y2); //取上面那么递归计算下面
t2=dfs(k-,x1,y1,x,y2); //去下面那么递归计算上面
t=min(t1+s[x1][y1][x][y2] , t2+s[x+][y1][x2][y2]);
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],t);
}
}
if(y2>y1) //至少有两列才能竖着切
{
//1.选左边:dp[k][x1][y1][x2][y2]=s[x1][y1][x2][y]+dp[k-1][x1][y+1][x2][y2];
//2.选右边:dp[k][x1][y1][x2][y2]=s[x1][y+1][x2][y2]+dp[k-1][x1][y1][x2][y]; for(y=y1; y<y2; y++)
{
t1=dfs(k-,x1,y+,x2,y2); //选左边那么递归计算右边
t2=dfs(k-,x1,y1,x2,y); //选右边那么递归计算左边
t=min(t1+s[x1][y1][x2][y] , t2+s[x1][y+][x2][y2]);
dp[k][x1][y1][x2][y2]=min(dp[k][x1][y1][x2][y2],t);
}
} return dp[k][x1][y1][x2][y2];
}
int main()
{
int x1,x2,y1,y2,x,y,n;
scanf("%d",&n);
for(int i=; i<=; i++)
for(int j=; j<=; j++)
scanf("%d",&c[i][j]);
memset(dp,-,sizeof(dp));
for(x1=; x1<=; x1++)
for(x2=x1; x2<=; x2++)
for(y1=; y1<=; y1++)
for(y2=y1; y2<=; y2++)
{
int tmp=add(x1,y1,x2,y2);
dp[][x1][y1][x2][y2]=s[x1][y1][x2][y2]=tmp*tmp;
}
dfs(n,,,,);
double X,ans;
X=.*add(,,,);
X=(X/n)*(X/n);
cout<<X<<endl;
ans=sqrt(1.0*dp[n][][][][]/n-X);
printf("%.3f\n",ans);
return ;
}
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
 
状态的描述:
1.矩形区域,采用Excel的方法
左上角(x1,y1):右下角(x2,y2)
2.状态:
f(i,x1,y1,x2,y2)表示
把(x1,y1):(x2,y2)分割成i块的最小segma((x-x)^2)。
 
对任意的矩形区域,i=1时的f值可以直接求得。
 
 
3.状态转移:f(i,x1,y1,x2,y2)
(1)枚举x1<=x<x2,横向分割成上下两个矩形
(x1,y1):(x,y2) (x+1,y1):(x2,y2)
把(x1,y1):(x,y2)分割成(i-1)矩形:f(i-1,x1,y1,x,y2)
(x+1,y1):(x2,y2)作为1个矩形: f(1,x+1,y1,x2,y2)
或者f(1,x1,y1,x,y2)+f(i-1,x+1,y1,x2,y2)
(2)同理,枚举y1<=y<y2,纵向分割成左右两个矩形
(x1,y1):(x2,y) (x1,y+1):(x2,y2)
f(i-1,x1,y1,x2,y)+f(1,x1,y+1,x2,y2)
f(1,x1,y1,x2,y)+f(i-1,x1,y+1,X2,Y2)
 

NOI 193棋盘分割.cpp的更多相关文章

  1. POJ 1191 棋盘分割

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

  2. poj1191 棋盘分割【区间DP】【记忆化搜索】

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

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

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

  4. [NOI1999] 棋盘分割(推式子+dp)

    http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 156 ...

  5. POJ1991 NOI1999棋盘分割

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

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

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

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

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

  8. Qt之VLFeat SLIC超像素分割(Cpp版)

    源地址:http://yongyuan.name/blog/vlfeat-slic-with-qt.html 近段时间学了点Qt,恰好前段时间用借助VLfeat以及OpenCV捣鼓了SLIC超像素分割 ...

  9. POJ 1191棋盘分割问题

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

随机推荐

  1. 子类化窗口控件的窗口过程(系统级替换,与直接替换控件的WndProc方法不是一回事)

    要说灵活性,自然是比不上Delphi自带的覆盖WndProc,或者替换WndProc方法. unit Unit1; interface uses Windows, Messages, SysUtils ...

  2. android 随手记 自定义广播通知栏

    自定义通知栏图标?不是很简单么.自定义布局都不在话下! 是的,有xml布局文件当然一切都很简单,如果不给你布局文件用呢? 听我慢慢道来! 首先怎么创建一个通知呢? 1.new 一个 Notificat ...

  3. 【HDOJ】3451 Beat drop

    BFS.当水滴破裂飞溅后,直到碰到水滴才会停止(观察case1).同时,考虑当水滴飞溅到点(x,y)并且该点同一时间破裂的情况,该水滴算作吸收. /* 3451 */ #include <ios ...

  4. Vim默认保存文件路径的设置

    在_vimrc文件中添加: exec 'cd ' . fnameescape('F:\') F:\ 换成自己所需的路径,这样在vim中新建文件后直接用命令“ :w 文件名”就可以自动保存到已定义的路径 ...

  5. linux安装 Android Studio详细教程,支持性较差,需要安装最新底层库内核的linux

    安装 Android Studio详细教程 libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5 lib32z1 jdk1.8.0_25 android-st ...

  6. VLC打开.264文件

    昨天收到几个文件名是:xxx.264的文件,这种文件属于视频图像的raw files,即只包含视频数据.由于缺少视频头文件,所以一般播放器难以播放出来.网上很多介绍的是.H264文件如何打开,以及用一 ...

  7. C字符数组及其应用

    1.字符数组和其他数值类型的数组的定义引用和初始化都是相同的. 特别注意的是: 在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串. \0'是由C编译系统自动加上的. 2. C语言允许 ...

  8. [Audio processing] 常见语音特征 —— LPC

    共振峰产生的原理及其在音质上的体现,共振峰的分布位置是建立在声音产生媒介的共鸣物理结构基础上的(Resonant Physical Structure).   无论是人声还是乐器,它们的声音特性都源自 ...

  9. 浅谈二维RMQ

    针对一些二维区间最值问题,用一维RMQ来解决显然是不够的.所以,要改进算法.鉴于网上没有PASCAL版的RMQ标程与解析,所以小可在这里简单的讲一下. 核心思想和一维的一样,只是在计算区间时略有不同. ...

  10. 视频监控之VSCloud版本计划

    下个版本会加入 1.人脸检测和人脸识别功能 2. 车牌识别. https://code.google.com/p/vscloud/ 下载连接 https://sourceforge.net/proje ...