[POJ 1191] 棋盘分割
[题目链接]
http://poj.org/problem?id=1191
[算法]
f[i][j][k][l][m] 表示进行了i次切割,当前矩形的左上角左标为(j,k),右下角坐标为(k,l) , sigma( (x - x') ^ 2 ) 的最小值
[代码]
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 15 #define getsum(x1,y1,x2,y2) sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1] const int INF = 2e9; long long i,j,k,x,y,t,n; long long a[10][10]; double sum[10][10]; double cnt,ans; double f[MAXN][10][10][10][10]; double min(double x,double y) { return x < y ? x : y; } inline double sqr(double x) { return x * x; } int main() { scanf("%lld",&n); for (i = 1; i <= 8; i++) { for (j = 1; j <= 8; j++) { scanf("%lld",&a[i][j]); } } for (i = 1; i <= 8; i++) { for (j = 1; j <= 8; j++) { sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j]; } } cnt = sum[8][8] / n * 1.0; for (i = 1; i <= n; i++) { for (j = 1; j <= 8; j++) { for (k = 1; k <= 8; k++) { for (x = 1; x <= 8; x++) { for (y = 1; y <= 8; y++) { f[i][j][k][x][y] = INF; } } } } } for (i = 1; i <= 8; i++) f[1][1][1][i][8] = min(f[1][1][1][i][8],sqr(getsum(i + 1,1,8,8) - cnt)); for (i = 1; i <= 8; i++) f[1][i][1][8][8] = min(f[1][i][1][8][8],sqr(getsum(1,1,i - 1,8) - cnt)); for (i = 1; i <= 8; i++) f[1][1][1][8][i] = min(f[1][1][1][8][i],sqr(getsum(1,i + 1,8,8) - cnt)); for (i = 1; i <= 8; i++) f[1][1][i][8][8] = min(f[1][1][i][8][8],sqr(getsum(1,1,8,i - 1) - cnt)); for (i = 1; i < n; i++) { for (j = 1; j <= 8; j++) { for (k = 1; k <= 8; k++) { for (x = 1; x <= 8; x++) { for (y = 1; y <= 8; y++) { for (t = k; t < y; t++) f[i + 1][j][k][x][t] = min(f[i + 1][j][k][x][t],f[i][j][k][x][y] + sqr(getsum(j,t + 1,x,y) - cnt)); for (t = y; t > k; t--) f[i + 1][j][t][x][y] = min(f[i + 1][j][t][x][y],f[i][j][k][x][y] + sqr(getsum(j,k,x,t - 1) - cnt)); for (t = j; t < x; t++) f[i + 1][j][k][t][y] = min(f[i + 1][j][k][t][y],f[i][j][k][x][y] + sqr(getsum(t + 1,k,x,y) - cnt)); for (t = x; t > j; t--) f[i + 1][t][k][x][y] = min(f[i + 1][t][k][x][y],f[i][j][k][x][y] + sqr(getsum(j,k,t - 1,y) - cnt)); } } } } } ans = INF; for (i = 1; i <= 8; i++) { for (j = 1; j <= 8; j++) { for (x = 1; x <= 8; x++) { for (y = 1; y <= 8; y++) { if (f[n - 1][i][j][x][y] != INF) ans = min(ans,f[n - 1][i][j][x][y] + sqr(getsum(i,j,x,y) - cnt)); } } } } printf("%.3lf\n",1.0 * sqrt(ans / n)); return 0; }