一,题意:
中文题
二。分析:
主要利用压缩dp与记忆化搜索思想
三,代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> using namespace std; const int Big=20000000; int Mat[10][10]; int N; int sum[10][10]; int dp[20][10][10][10][10]; void unit() {//求和用sum[i][j]表示ij到左上角的和 int total; for(int i=1; i<=8; i++) for(int j=1; j<=8; j++) { total=Mat[i][j]; int x_1,y_1; x_1=i-1; y_1=j-1; if(x_1>0) total+=sum[x_1][j]; if(y_1>0) total+=sum[i][y_1]; if(x_1>0&&y_1>0) total-=sum[x_1][y_1]; sum[i][j]=total; } } int account(int x_1,int y_1,int x_2,int y_2) {//求(x_1,y_1)到(x_2。y_2)区间和 int total=sum[x_2][y_2]; int x_3,y_3; x_3=x_1-1; y_3=y_1-1; if(x_3>0) total-=sum[x_3][y_2]; if(y_3>0) total-=sum[x_2][y_3]; if(x_3>0&&y_3>0) total+=sum[x_3][y_3]; return total*total; } int solve(int k,int x_1,int y_1,int x_2,int y_2) {//记忆化dp if(dp[k][x_1][y_1][x_2][y_2]!=-1) return dp[k][x_1][y_1][x_2][y_2]; if(k==1) return dp[k][x_1][y_1][x_2][y_2]=account(x_1,y_1,x_2,y_2); if(k>1) { int Min=Big; for(int i=y_1;i<y_2;i++) {//横向分割 int first=account(x_1,y_1,x_2,i); int second=account(x_1,i+1,x_2,y_2); first+=solve(k-1,x_1,i+1,x_2,y_2); second+=solve(k-1,x_1,y_1,x_2,i); if(first>second) first=second; if(Min>first) Min=first; } for(int j=x_1;j<x_2;j++) {//纵向分割 int first=account(x_1,y_1,j,y_2); int second=account(j+1,y_1,x_2,y_2); first+=solve(k-1,j+1,y_1,x_2,y_2); second+=solve(k-1,x_1,y_1,j,y_2); if(first>second) first=second; if(Min>first) Min=first; } return dp[k][x_1][y_1][x_2][y_2]=Min; } return dp[k][x_1][y_1][x_2][y_2]=Big; } int main() { while(scanf("%d",&N)!=EOF) { double total=0.0; for(int i=1; i<=8; i++) for(int j=1; j<=8; j++) { scanf("%d",&Mat[i][j]); total+=Mat[i][j]; } unit(); memset(dp,-1,sizeof(dp)); total=(total/N)*(total/N); double key=solve(N,1,1,8,8); key=key/N; key=sqrt(key-total); printf("%0.3f ",key); } return 0; }