题意:
将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差
,其中平均值
,x
i为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。

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


请编程对给出的棋盘及n,求出O'的最小值。
分析:
将公式化简可以得到
σ
2
= 1/n*∑xi
2
- ¯x,
也就是只需要使
∑xi
2
最小即可
;
我们用dp[a][i][j][k][s]表示第a次切割(i,j,k,s)棋盘的最小值;
则有
minmin=min(minmin,min(dp[a-1][i][j][m][s]+t*t,dp[a-1][m+1][j][k][s]+t2*t2)); (i<=m<k)
minmin=min(minmin,min(dp[a-1][i][j][k][m]+t*t,dp[a-1][i][m+1][k][s]+t2*t2)); (j<=m<s)
dp[a][i][j][k][s]=minmin;
poj1191 :
http://poj.org/problem?id=1191
参考代码:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
#define inf 0xffffff
int n,a[10][10],sum[10][10];
int dp[15][10][10][10][10];
int countsum(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){
//初始化
for (int i=0;i<8;i++)
for (int j=0;j<8;j++)
for (int k=0;k<8;k++)
for (int s=0;s<8;s++){
int t=countsum(i,j,k,s);
dp[0][i][j][k][s]=t*t;
}
for (int a=1;a<=k;a++){
for (int i=0;i<8;i++){
for (int j=0;j<8;j++){
for (int k=0;k<8;k++){
for (int s=0;s<8;s++){
int minmin = inf;
if ((k-i+1)*(s-j+1)<a+1){
dp[a][i][j][k][s]=minmin;
continue;
}
for (int m=i;m<k;m++){
int t=countsum(m+1,j,k,s);
int t2=countsum(i,j,m,s);
minmin=min(minmin,min(dp[a-1][i][j][m][s]+t*t,dp[a-1][m+1][j][k][s]+t2*t2));
}
for (int m=j;m<s;m++){
int t=countsum(i,m+1,k,s);
int t2=countsum(i,j,k,m);
minmin=min(minmin,min(dp[a-1][i][j][k][m]+t*t,dp[a-1][i][m+1][k][s]+t2*t2));
}
dp[a][i][j][k][s]=minmin;
}
}
}
}
}
return dp[k][0][0][7][7];
}
int main(){
while (cin>>n){
for (int i=0;i<8;i++){
int s=0;
for (int j=0;j<8;j++){
cin>>a[i][j];
s+=a[i][j];
if (i==0)
sum[i][j]=s;
else
sum[i][j]=sum[i-1][j]+s;
}
}
double ans = n*fun(n-1)-sum[7][7]*sum[7][7];
cout<<fixed<<setprecision(3)<<sqrt(ans/(n*n))<<endl;
}
return 0;
}
用C++提交答案是WA 用G++就AC了。。。