poj1191--棋盘分割(dp)

2024-08-25 00:58
文章标签 dp 分割 棋盘 poj1191

本文主要是介绍poj1191--棋盘分割(dp),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

棋盘分割
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 12671 Accepted: 4497

Description

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

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
x i为第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)方块的右下角。

dp[i][j] i表示当前分割为i块是,并且,最后一块为j,j = x1 * 1000 + y1 * 100 + x2 * 10 + y2,将一个方块的坐标压到一个数中,让dp[i][j]最小,最终得到dp[n][j]找出最小值

对于每一个方块枚举可以切开的位置,和之后得到的方块,。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std ;
#define LL __int64
#define INF 0x3f3f3f3f
int Map[10][10] ;
double dp[20][11000] ;
double f(int x1,int y1,int x2,int y2,double x)
{
double ans ;
ans = Map[x2][y2] - Map[x2][y1] - Map[x1][y2] + Map[x1][y1] ;
ans = ( ans - x ) * ( ans - x ) ;
return ans ;
}
int main()
{
int i , j , k , l , n , x1 , y1 , x2 , y2 ;
double x = 0 , ans = INF , temp , temp1 , temp2 ;
scanf("%d", &n) ;
memset(Map,0,sizeof(Map)) ;
for(i = 1 ; i <= 8 ; i++)
{
for(j = 1 ; j <= 8 ; j++)
{
scanf("%d", &Map[i][j]) ;
Map[i][j] += Map[i][j-1] ;
}
for(j = 1 ; j <= 8 ; j++)
Map[i][j] += Map[i-1][j] ;
}
/*for(i = 0 ; i <= 8 ; i++)
{
for(j = 0 ; j <= 8 ; j++)
printf("%d ", Map[i][j]) ;
printf("\n") ;
}*/
x = Map[8][8]*1.0/n ;
//printf("%lf\n", x) ;
for(i = 0 ; i <= n ; i++)
for(j = 0 ; j <= 8888 ; j++)
dp[i][j] = INF ;
dp[1][88] = (Map[8][8]*1.0 - x) * (Map[8][8]*1.0 - x) ;
for(i = 1 ; i < n ; i++)
{
for(j = 0 ; j <= 8888 ; j++)
{
x1 = j/1000%10 ;
y1 = j/100%10 ;
x2 = j/10%10 ;
y2 = j%10 ;
temp = f(x1,y1,x2,y2,x) ;
for(k = x1+1 ; k < x2 ; k++)
{
temp1 = f(x1,y1,k,y2,x) ;
temp2 = f(k,y1,x2,y2,x) ;
l = x1*1000+y1*100+k*10+y2 ;
if( dp[i+1][l] > dp[i][j] - temp + temp1 + temp2 )
dp[i+1][l] = dp[i][j] - temp + temp1 + temp2 ;
l = k*1000+y1*100+x2*10+y2 ;
if( dp[i+1][l] > dp[i][j] - temp + temp1 + temp2 )
dp[i+1][l] = dp[i][j] - temp + temp1 + temp2 ;
}
for(k = y1+1 ; k < y2 ; k++)
{
temp1 = f(x1,y1,x2,k,x) ;
temp2 = f(x1,k,x2,y2,x) ;
l = x1*1000+y1*100+x2*10+k ;
if( dp[i+1][l] > dp[i][j] - temp + temp1 + temp2 )
dp[i+1][l] = dp[i][j] - temp + temp1 + temp2 ;
l = x1*1000+k*100+x2*10+y2 ;
if( dp[i+1][l] > dp[i][j] - temp + temp1 + temp2 )
dp[i+1][l] = dp[i][j] - temp + temp1 + temp2 ;
}
}
}
for(j = 0 ; j <= 8888 ; j++)
ans = min(ans,dp[n][j]) ;
printf("%.3lf\n", sqrt(ans/(n*1.0))) ;
return 0;
}

这篇关于poj1191--棋盘分割(dp)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1104102

相关文章

使用Python实现批量分割PDF文件

《使用Python实现批量分割PDF文件》这篇文章主要为大家详细介绍了如何使用Python进行批量分割PDF文件功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、架构设计二、代码实现三、批量分割PDF文件四、总结本文将介绍如何使用python进js行批量分割PDF文件的方法

使用Python将长图片分割为若干张小图片

《使用Python将长图片分割为若干张小图片》这篇文章主要为大家详细介绍了如何使用Python将长图片分割为若干张小图片,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果1. Python需求

C#中字符串分割的多种方式

《C#中字符串分割的多种方式》在C#编程语言中,字符串处理是日常开发中不可或缺的一部分,字符串分割是处理文本数据时常用的操作,它允许我们将一个长字符串分解成多个子字符串,本文给大家介绍了C#中字符串分... 目录1. 使用 string.Split2. 使用正则表达式 (Regex.Split)3. 使用

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl