您的位置:首页 > 其它

POJ 1191 棋盘分割 DP

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



原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。 
题解:主要弄明白均方差的转换公式即可。 刘汝佳书116页。

#include <cmath>
#include <iostream>
using namespace std;

#define N 9
#define INF 999999999
int s

, dp[15]

;

int min ( int a, int b )
{
return a < b ? a : b;
}

int count ( int k, int x1, int y1, int x2, int y2 )
{
int c, ans = INF;
for ( c = x1 + 1; c < x2; c++ )
{
ans = min ( dp[k-1][x1][y1][c][y2] + dp[0][c][y1][x2][y2], ans );
ans = min ( dp[k-1][c][y1][x2][y2] + dp[0][x1][y1][c][y2], ans );
}

for ( c = y1 + 1; c < y2; c++ )
{
ans = min ( dp[k-1][x1][y1][x2][c] + dp[0][x1][c][x2][y2], ans );
ans = min ( dp[k-1][x1][c][x2][y2] + dp[0][x1][y1][x2][c], ans );
}
return ans;
}

int main()
{
int n, i, j, x1, y1, x2, y2, map, area;
scanf("%d",&n);
memset(s,0,sizeof(s));
for ( i = 1; i <= 8; i++ )
{
for ( j = 1; j <= 8; j++ )
{
scanf("%d",&map);
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + map;
}
}

for ( x1 = 0; x1 < 8; x1++ )
{
for ( y1 = 0; y1 < 8; y1++ )
{
for ( x2 = x1+1; x2 <= 8; x2++ )
{
for ( y2 = y1+1; y2 <= 8; y2++ )
{
area = s[x2][y2] - s[x2][y1] - s[x1][y2] + s[x1][y1];
dp[0][x1][y1][x2][y2] = area * area;
}
}
}
}

for ( i = 1; i < n; i++ )
{
for ( x1 = 0; x1 < 8; x1++ )
{
for ( y1 = 0; y1 < 8; y1++ )
{
for ( x2 = x1+1; x2 <= 8; x2++ )
{
for ( y2 = y1+1; y2 <= 8; y2++ )
dp[i][x1][y1][x2][y2] = count ( i, x1, y1, x2, y2 );
}
}
}
}

double ans = dp[n-1][0][0][8][8] * 1.0 / n - pow ( s[8][8]*1.0/n, 2 );
printf("%.3lf\n", sqrt(ans));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c