化简一下那个方差得到:$$sqrtfrac{(Sigma_{i=1}^nx_i)-nar x^2}{n}$$
除了$Sigma_{i=1}^nx_i$这部分未知,其余已知,而那部分显然越大越好,很容易用DP去转移求得。
- dp[n][x1][y1][x2][y2]表示当前要切的矩形是(x1,y1,x2,y2)且还需要切n刀得到的最大的那部分的值
- 通过横竖切来转移,用记忆化搜索很容易实现
WA了好多发,听说有精度问题,一直搞精度,原来一个地方是爆int了。。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<29) 7 int d[16][8][8][8][8]; 8 int a[8][8]; 9 int calc(int x1,int y1,int x2,int y2){ 10 int res=0; 11 for(int i=x1; i<=x2; ++i){ 12 for(int j=y1; j<=y2; ++j) res+=a[i][j]; 13 } 14 return res; 15 } 16 int dp(int k,int x1,int y1,int x2,int y2){ 17 if(d[k][x1][y1][x2][y2]!=-1) return d[k][x1][y1][x2][y2]; 18 if(k==0) return d[k][x1][y1][x2][y2]=calc(x1,y1,x2,y2)*calc(x1,y1,x2,y2); 19 int res=INF; 20 for(int i=x1; i<x2; ++i){ 21 res=min(res,dp(k-1,x1,y1,i,y2)+calc(i+1,y1,x2,y2)*calc(i+1,y1,x2,y2)); 22 res=min(res,dp(k-1,i+1,y1,x2,y2)+calc(x1,y1,i,y2)*calc(x1,y1,i,y2)); 23 } 24 for(int i=y1; i<y2; ++i){ 25 res=min(res,dp(k-1,x1,y1,x2,i)+calc(x1,i+1,x2,y2)*calc(x1,i+1,x2,y2)); 26 res=min(res,dp(k-1,x1,i+1,x2,y2)+calc(x1,y1,x2,i)*calc(x1,y1,x2,i)); 27 } 28 return d[k][x1][y1][x2][y2]=res; 29 } 30 int main(){ 31 memset(d,-1,sizeof(d)); 32 int n; 33 scanf("%d",&n); 34 int sum=0; 35 for(int i=0; i<8; ++i){ 36 for(int j=0; j<8; ++j) scanf("%d",&a[i][j]),sum+=a[i][j]; 37 } 38 double avg=sum*1.0/n; 39 double ans = sqrt(dp(n-1,0,0,7,7)*1.0/n-avg*avg); 40 printf("%.3f ",ans); 41 return 0; 42 }