棋盘分割
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 11457 | Accepted: 4032 |
Description
将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差 ,其中平均值 ,x i为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差 ,其中平均值 ,x i为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。
Input
第1行为一个整数n(1 < n < 15)。
第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
Output
仅一个数,为O'(四舍五入精确到小数点后三位)。
Sample Input
3 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 3
Sample Output
1.633
Source Code Problem: 1191 Memory: 596K Time: 0MS Language: C++ Result: Accepted Source Code #include <iostream> #include <cmath> using namespace std; const int maxint = 2000000000; # define N 8 double ans; int map[ N+1 ][ N+1 ], n; int sum[ N+1 ][ N+1 ]; int f[16][ N+1 ][ N+1 ][ N+1 ][ N+1 ]; void init(){ for (int i = 1; i <= N; i ++) for (int j = 1; j <= N; j++) scanf("%d", &map[i][j]); } void output(){ printf("%.3lf\n", ans); } int cal_sum(int x1, int y1, int x2, int y2){ int tmp = sum[x2][y2]+sum[x1-1][y1-1] - sum[x1-1][y2]-sum[x2][y1-1]; return tmp*tmp; } void dp(){ memset(sum, 0, sizeof(sum)); int tmp; sum[0][0] = 0; for (int i = 1; i <= N; i ++) for (int j = 1; j <= N; j ++) sum[i][j] = sum[i][j-1]+sum[i-1][j] - sum[i-1][j-1] + map[i][j]; memset(f, 0, sizeof(f)); for(int x1 = 1; x1 <= N; x1 ++) for (int y1 = 1; y1 <= N; y1 ++) for (int x2 = x1; x2 <= N; x2 ++) for (int y2 = y1; y2 <= N; y2 ++) f[1][x1][y1][x2][y2] = cal_sum(x1, y1, x2, y2); for (int k = 2; k <= n; k ++) for (int x1 = 1; x1 <= N; x1 ++) for (int y1 = 1; y1 <= N; y1 ++) for (int x2 = x1; x2 <= N; x2 ++) for (int y2 = y1; y2 <= N; y2 ++){ f[k][x1][y1][x2][y2] = maxint; for (int x = x1; x < x2; x ++){ tmp = min(f[k-1][x1][y1][x][y2] + cal_sum(x+1, y1, x2, y2), f[k-1][x+1][y1][x2][y2] + cal_sum(x1, y1, x, y2)); if (f[k][x1][y1][x2][y2] > tmp) f[k][x1][y1][x2][y2] = tmp; } for (int y = y1; y < y2; y ++){ tmp = min( f[k-1][x1][y1][x2][y] + cal_sum(x1, y+1, x2, y2), f[k-1][x1][y+1][x2][y2] + cal_sum(x1, y1, x2, y) ); if (f[k][x1][y1][x2][y2] > tmp) f[k][x1][y1][x2][y2] = tmp; } } ans = sqrt( f[n][1][1][N][N]/(double)n - sum[N][N]*sum[N][N]/(double)(n*n)); } int main() { while (scanf("%d", &n) != EOF){ init(); dp(); output(); } return 0; }