1
#include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int N = (1 << 8) + 1; 6 7 int n, m; 8 9 double a[N][N], dp[9][N][N]; 10
//二维数组的子矩阵和 11 double sum(int x, int y, int xx, int yy) { return a[x][y] - a[xx][y] - a[x][yy] + a[xx][yy]; } 12 13 int main() { 14 ios::sync_with_stdio(false); 15 cin.tie(nullptr); 16 cin >> n; 17 m = (1 << n); 18 for (int i = 1; i <= m; i++) { 19 for (int j = 1; j <= m; j++) { 20 cin >> a[i][j]; 21 a[i][j] += a[i - 1][j]; 22 a[i][j] += a[i][j - 1]; 23 a[i][j] -= a[i - 1][j - 1];//二维前缀和预处理 24 } 25 } 26 for (int l = n - 1; l >= 0; l--) {//倒着dp 27 int k = 1 << l, b = 1 << (n - l); 28 for (int i = m; i - k >= 0; i--) { //i-k,j-k与 0 比较防止越界 29 for (int j = m; j - k >= 0; j--) { 30 double last = 0; 31 for (int ii = min(i + k, m); ii >= i; ii--) { 32 for (int jj = min(j + k, m); jj >= j; jj--) { 33 last = max(last, dp[l + 1][ii][jj]);//数据量较小,暴力地更新max即可 34 } 35 }
// dp[l][i][j] = max([ min(i+k,m) >= ii >= 0 ][ min(j+k,m) >= jj >= 0] dp[l+1][ii][jj])]
+ (sum[(i-k,j-k),(i,j)] / log2(边长))
//为什么要除以b(1<<days?)因为每天掉发的数量都相当于前一天相同区域的一半 36 dp[l][i][j] = last + sum(i - k, j - k, i, j) / b; 37 } 38 } 39 } 40 double ans = 0; 41 for (int i = 1; i <= m; i++) { 42 for (int j = 1; j <= m; j++) { 43 ans = max(ans, dp[0][i][j]);//找到最大值 44 } 45 } 46 cout << fixed << setprecision(1); 47 cout << sum(0, 0, m, m) - ans << '\n';//结论就是 原始的总量 减去 掉发的最大值 48 return 0; 49 }