ACWing 321 棋盤分割

2021-10-21 17:17:56 字數 3310 閱讀 6327

將乙個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 將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩...