1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| // Problem: 棋盘分割 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/323/ // Memory Limit: 10 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h> using namespace std; #define ll long long //# define int long long #define ull unsigned long long #define pii pair<int,int>
#define baoliu(x, y) cout << fixed << setprecision(y) << x #define endl "\n" #define debug1(x) cerr<<x<<" " #define debug2(x) cerr<<x<<endl const int N = 17; const int M = 1e6 + 10; const int inf = 0x3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; int n, m; int a[N][N];
double avg=0; double get(int x1, int y1,int x2,int y2){ double res=a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1]; res-=avg; return res*res; } //只需要割k-1次 double f[N][N][N][N][N]; double dp(int k,int x1,int y1,int x2,int y2){ double &u=f[k][x1][y1][x2][y2]; if(u>=0)return u; if(k==m){ //不存在第m次切割,m-1次以后就满足要求,直接返回这个棋盘的贡献 return u=get(x1,y1,x2,y2); } double tmp=1e9; for(int i=x1;i<x2;i++){ tmp=min(tmp,dp(k+1,x1,y1,i,y2)+get(i+1,y1,x2,y2)); tmp=min(tmp,dp(k+1,i+1,y1,x2,y2)+get(x1,y1,i,y2)); // tmp=min(tmp,dp[k+1][x1][y1][i][y2]+get(i+1,y1,x2,y2)); // tmp=min(tmp,dp[k+1][i+1][y1][x2][y2]+get(x1,y1,i,y2)); } for(int i=y1;i<y2;i++){ tmp=min(tmp,dp(k+1,x1,y1,x2,i)+get(x1,i+1,x2,y2)); tmp=min(tmp,dp(k+1,x1,i+1,x2,y2)+get(x1,y1,x2,i)); // tmp=min(tmp,dp[k+1][x1][y1][x2][i]+get(x1,i+1,x2,y2)); // tmp=min(tmp,dp[k+1][x1][i+1][x2][y2]+get(x1,y1,x2,i)); } return u=tmp; } void solve(){ n=8; cin>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=8;j++){ cin>>a[i][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ a[i][j]+=a[i-1][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ a[i][j]+=a[i][j-1]; } } avg=(double)a[n][n]/(double)m; // cerr<<avg<<endl; memset(f,-1,sizeof f); //初始状态有一个盘 //当前已经对棋盘k-1次切割,有k个棋盘 //k次划分后选择的棋盘是 左上角为 x1y1,右下角x2y2 double ans=dp(1,1,1,n,n); // cerr<<ans<<endl; ans=sqrt(ans/(double)m); baoliu(ans,3); } int main() { cin.tie(0); ios::sync_with_stdio(false);
int t; //cin>>t; t=1; while (t--) { solve(); } return 0; }
|