將乙個8×8
8×88×
8的棋盤進行如下分割:將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了(n−
1)(n−1)
(n−1
)次後,連同最後剩下的矩形棋盤共有n
nn塊矩形棋盤。每次切割都只能沿著棋盤格仔的邊進行,例如下面的兩個圖,右圖裡中間豎著切一刀之後,不能繼續在左右兩邊切了,只能在一邊切;左圖就是滿足條件的。
原棋盤上每一格有乙個分值,一塊矩形棋盤的總分為其所含各格分值之和。現在需要把棋盤按上述規則分割成n
nn塊矩形棋盤,並使各矩形棋盤總分的均方差最小。均方差σ=∑
i=1n
(xi−
xˉ)2
n\sigma = \sqrt^n(x_i-\bar)^2}}
σ=n∑i=
1n(
xi−
xˉ)2
,其中平均值xˉ=
∑i=1
nxin
\bar=\frac^x_i}
xˉ=n∑i
=1n
xi
,x
ix_i
xi為第i
ii塊矩形棋盤的總分。請程式設計對給出的棋盤及n
nn,求出均方差的最小值。
輸入格式:
第1
11行為乙個整數n
nn。第2
22行至第9
99行每行為8
88個小於100
10010
0的非負整數,表示棋盤上相應格仔的分值。每行相鄰兩數之間用乙個空格分隔。
輸出格式:
輸出最小均方差值(四捨五入精確到小數點後三位)。
資料範圍:
1
<
n<151
1<
n<15
思路是記憶化搜尋。設f[x
1][y
1][x
2][y
2][k
]f[x_1][y_1][x_2][y_2][k]
f[x1]
[y1
][x2
][y
2][
k]是將以(x1
,y1)
(x_1,y_1)
(x1,y
1)為左上角,(x2
,y2)
(x_2,y_2)
(x2,y
2)為右下角的矩形按上述法則切割為k
kk塊時的最小均方差的平方除以n
nn。我們可以按照第一刀是怎麼切的來分類。第一刀切割方式可以分為豎著切和橫著切。比如可以列舉豎著切的那一刀是在哪列的右邊沿,選項有x1,
x1+1
,...
,x2−
1x_1,x_1+1,...,x_2-1
x1,x1
+1,
...,
x2−
1,切割完畢之後,還需要列舉是繼續切左半部分還是有半部分,對於不再切割的那半部分,它對f
ff的貢獻就是,設其和為s
ss,則貢獻為1n(
s−xˉ
)2\frac(s-\bar)^2
n1(s−
xˉ)2
。所以在豎著切的情形下,有:f[x
1][y
1][x
2][y
2][k
]=min
f[x_1][y_1][x_2][y_2][k]=\min\(\sum a[(x_1,c+1):(x_2,y_2)]-\bar)^2,\\\frac(\sum a[(x_1,y_1):(x_2,c)]-\bar)^2+f[x_1][c+1][x_2][y_2][k-1]\}
f[x1]
[y1
][x2
][y
2][
k]=min
接著類似考慮橫著切的情形,四種情況取最小值即可,但最後要返回f[1
][1]
[8][
8][n
]\sqrt
f[1][1
][8]
[8][
n]。為了**方便,可以用記憶化搜尋來做。同時可以預處理出二維字首和,加快子矩陣求和的速度。**如下:
#include
#include
#include
using
namespace std;
const
int n =
15, m =9;
const
double inf =
1e8;
int n, m =8;
int s[n]
[n];
double f[m]
[m][m]
[m][n]
;// 存矩陣和除以n
double x;
// 返回左上角是(x1, y1),右下角是(x2, y2)的子矩陣對f的貢獻
double
get_divn
(int x1,
int y1,
int x2,
int y2)
// 返回如果切割左上角是(x1, y1),右下角是(x2, y2)的子矩陣,一共切k次,該子矩陣對f的最小貢獻
double
dfs(
int x1,
int y1,
int x2,
int y2,
int k)
// 列舉豎著切
for(
int i = y1; i < y2; i++
)return v;
}int
main()
memset
(f,-1,
sizeof f)
;// x存整個矩陣的和除以n
x =(double
) s[m]
[m]/ n;
printf
("%.3lf\n"
,sqrt
(dfs(1
,1,8
,8, n)))
;return0;
}
時空複雜度本質上是o(1
)o(1)
o(1)
的,因為棋盤本身是8×8
8\times 8
8×8的,n
nn最多就取14
1414
,所以f
ff陣列整個空間也是個常數。
AcWing 321 棋盤分割
題目傳送門 給定乙個 8 8 的棋盤,棋盤的每個小方格都有乙個權值 w x,w y 每次我們可以對棋盤進行一次橫或豎切,將棋盤分成兩塊矩形的子棋盤 分割完一次後,我們可以選擇兩個子棋盤中的乙個再繼續遞迴操作。可以發現題目中給的這個,右邊這個並不是遞迴下去做的 他對第一次分割的兩個矩形又分別進行了分割...
F 棋盤分割
將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了 n 1 次後,連同最後剩下的矩形棋盤共有n塊矩形棋盤。每次切割都只能沿著棋盤格仔的邊進行 原棋盤上每一格有乙個分值,一塊矩形棋盤的總分為其所含各格分值之和。現在需要把棋盤按上述規則分割成n...
遞迴 棋盤分割問題
language default 棋盤分割 time limit 1000ms memory limit 10000k total submissions 11819 accepted 4175 description 將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩...