思路:dp[n][x1][y1][x2][y2],表示还剩n刀可以切,当前矩形位置为左上角(x1,y1), 右下角(x2,y2),
然后把公式转化下,其实就是求平方和最小
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 10;
const double INF = 1e18;
int n, vis[15][N][N][N][N];
double num[N][N], sum[N][N], dp[15][N][N][N][N];
double get(int x1, int y1, int x2, int y2) {
double tmp = sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
tmp *= tmp;
return tmp;
}
double dfs(int n, int x1, int y1, int x2, int y2) {
if (vis[n][x1][y1][x2][y2]) return dp[n][x1][y1][x2][y2];
vis[n][x1][y1][x2][y2] = 1;
double &ans = dp[n][x1][y1][x2][y2];
ans = INF;
if (n == 1) return ans = get(x1, y1, x2, y2);
for (int i = x1; i < x2; i++) {
ans = min(ans, dfs(n - 1, i + 1, y1, x2, y2) + get(x1, y1, i, y2));
ans = min(ans, dfs(n - 1, x1, y1, i, y2) + get(i + 1, y1, x2, y2));
}
for (int i = y1; i < y2; i++) {
ans = min(ans, dfs(n - 1, x1, i + 1, x2, y2) + get(x1, y1, x2, i));
ans = min(ans, dfs(n - 1, x1, y1, x2, i) + get(x1, i + 1, x2, y2));
}
return ans;
}
int main() {
while (~scanf("%d", &n)) {
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++) {
scanf("%lf", &num[i][j]);
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + num[i][j];
}
memset(vis, 0, sizeof(vis));
printf("%.3lf\n", sqrt(dfs(n, 1, 1, 8, 8) / n - (sum[8][8] * sum[8][8] / n / n)));
}
return 0;
}