您的位置:首页 > 其它

Poj 1191 棋盘分割

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

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。

均方差 ,其中平均值 ,xi为第i块矩形棋盘的总分。

请编程对给出的棋盘及n,求出O'的最小值。

思路:lrj《算法与信息学竞赛》中P116的例题。dp[k][x1][y1][x2][y2]:左上角坐标为(x1,y1),右下角坐标为(x2,y2)

的棋盘,设它把切割k次以后得到的k+1块矩形的总分平方和最小值。

s[x1][y1][x2][y2]:左上角坐标为(x1,y1),右下角坐标为(x2,y2)。

的棋盘的总和的平方

状态转移方程dp[k][x1][y1][x2][y2] =

1)按横的划分: min(dp[k-1][x1][y1][f][y2]+s[f+1][y1][x2][y2] , dp[k-1][f+1][y1][x2][y2]+s[x1][y1][f][y2]);

2)按竖的划分: min(dp[k-1][x1][y1][x2][f]+s[x1][f+1][x2][y2], dp[k-1][x1][f+1][x2][y2]+s[x1][y1][x2][f]);

/*
dp[k][x1][y1][x2][y2]:左上角坐标为(x1,y1),右下角坐标为(x2,y2)
的棋盘,设它把切割k次以后得到的k+1块矩形的总分平方和最小值.

s[x1][y1][x2][y2]:左上角坐标为(x1,y1),右下角坐标为(x2,y2)
的棋盘的总和的平方

dp[k][x1][y1][x2][y2] =
1)按横的划分:    min(dp[k-1][x1][y1][f][y2]+s[f+1][y1][x2][y2]
, dp[k-1][f+1][y1][x2][y2]+s[x1][y1][f][y2]);

2)按竖的划分:    min(dp[k-1][x1][y1][x2][f]+s[x1][f+1][x2][y2]
, dp[k-1][x1][f+1][x2][y2]+s[x1][y1][x2][f]);
*/
#include <stdio.h>
#include <memory.h>
#include <math.h>
int n;
int dp[16][10][10][10][10];
int data[10][10];
int s[10][10][10][10];
void get_sum(int x1,int y1,int x2,int y2) {
int i,j,sum;

sum=0;

if (s[x1][y1][x2][y2]!=0)
return;
for (i=x1;i<=x2;i++) {
for (j=y1;j<=y2;j++) {
sum=sum+data[i][j];
}
}
s[x1][y1][x2][y2]=sum*sum;
}
int min_num(int a,int b) {
if (a>b)
return b;
return a;
}
int main()
{
int i,j,k,g,h,l,temp;
double sum,average,result;

scanf("%d",&n);
sum=0;
for (i=1;i<=8;i++) {
for (j=1;j<=8;j++) {
scanf("%d",&data[i][j]);
sum+=data[i][j];
}
}
average=sum/n;
memset(s,0,sizeof(s));
for (i=1;i<=8;i++) {
for (j=1;j<=8;j++) {
for (g=i;g<=8;g++) {
for (h=j;h<=8;h++) {
get_sum(i,j,g,h);
dp[0][i][j][g][h]=s[i][j][g][h];

}
}
}
}
for (k=1;k<n;k++) {
for (i=1;i<=8;i++) {
for (j=1;j<=8;j++) {
for (g=i;g<=8;g++) {
for (h=j;h<=8;h++) {
dp[k][i][j][g][h]=10000000;
for (l=i;l<g;l++) {
get_sum(l+1,j,g,h);
temp=min_num(dp[k-1][i][j][l][h]+s[l+1][j][g][h],dp[k-1][l+1][j][g][h]+s[i][j][l][h]);
dp[k][i][j][g][h]=min_num(temp, dp[k][i][j][g][h]);
}
for (l=j;l<h;l++) {
get_sum(i,l+1,g,h);
temp=min_num(dp[k-1][i][j][g][l]+s[i][l+1][g][h],dp[k-1][i][l+1][g][h]+s[i][j][g][l]);
dp[k][i][j][g][h]=min_num(temp, dp[k][i][j][g][h]);
}
}
}
}
}
}
result=(double)dp[n-1][1][1][8][8]/n-average*average;
printf("%.3lf\n",sqrt(result));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: