You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.2 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 9, M = 15;
const double INF = 0x3f3f3f3f;
double s[N][N]; // 矩阵前缀和
int n;
int m = 8;
double f[N][N][N][N][M];
double get(int x1, int y1, int x2, int y2) {
double X = s[m][m] / n;
double sum = s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];
sum = sum - X;
return sum * sum / n;
}
void init() {
for (int k = 0; k < M; k++) // 注意先枚举剩余刀数
for (int x1 = 1; x1 <= 8; x1++)
for (int y1 = 1; y1 <= 8; y1++)
for (int x2 = x1; x2 <= 8; x2++)
for (int y2 = y1; y2 <= 8; y2++)
if (k)
f[x1][y1][x2][y2][k] = INF; // 其他状态都没有到达
else
f[x1][y1][x2][y2][k] = get(x1, y1, x2, y2); // 切割0次
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++) {
scanf("%lf", &s[i][j]);
s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
}
init();
// k的含义是剩余的刀数为阶段概念,需要写在外层循环
for (int k = 1; k < n; k++)
for (int x1 = 1; x1 <= 8; x1++)
for (int y1 = 1; y1 <= 8; y1++)
for (int x2 = x1; x2 <= 8; x2++)
for (int y2 = y1; y2 <= 8; y2++) {
double &v = f[x1][y1][x2][y2][k];
// 横切
for (int i = x1; i < x2; i++) {
v = min(v, f[x1][y1][i][y2][k - 1] + get(i + 1, y1, x2, y2)); // 选上边,加下面
v = min(v, f[i + 1][y1][x2][y2][k - 1] + get(x1, y1, i, y2)); // 选下边
}
// 纵切
for (int i = y1; i < y2; i++) {
v = min(v, f[x1][y1][x2][i][k - 1] + get(x1, i + 1, x2, y2)); // 选左边,加右边
v = min(v, f[x1][i + 1][x2][y2][k - 1] + get(x1, y1, x2, i)); // 选右边
}
}
printf("%.3f\n", sqrt(f[1][1][8][8][n - 1]));
return 0;
}