题意:
将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差,其中平均值,xi为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O‘的最小值。
分析:
将公式化简可以得到σ2 =
1/n*∑xi2 - ˉx,也就是只需要使∑xi2最小即可;
我们用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了。。。
时间: 2024-10-06 23:07:48