AcWing 321 棋盤分割

2022-09-10 17:30:23 字數 1775 閱讀 3886

題目傳送門

給定乙個 \(8×8\) 的棋盤,棋盤的每個小方格都有乙個權值 \(w_x,w_y\)

每次我們可以對棋盤進行一次切,將棋盤分成兩塊矩形的子棋盤

分割完一次後,我們可以選擇兩個子棋盤中的乙個再繼續遞迴操作。

可以發現題目中給的這個,右邊這個並不是遞迴下去做的:他對第一次分割的兩個矩形又分別進行了分割(題目要求我們只能保留乙個繼續分割)

現需要把棋盤按照上述分割方案,分成 \(n\) 塊(\(n−1\) 次劃分操作)

求乙個劃分方案,使得各子棋盤的總分的均方差最小

不難發現,遞迴操作會有很多冗餘的重複計算,於是我們可以採用記憶化搜尋進行優化

\(f[x_1,y_1,x_2,y_2,k]\) 表示這個區間在剩餘\(k\)刀的情況下,可以獲取到的計算公式最大值

#include using namespace std;

const int n = 10; //8*8個格仔,我們從下標1開始放入,需要用到下標8,開9個。

const int inf = 0x3f3f3f3f;

int n;

int m = 8;

int s[n][n]; //二維字首和

double f[n][n][n][n][n]; //dp結果陣列

double x; //平均值

//二維字首和

int get_sum(int x1, int y1, int x2, int y2)

//均方差公式

double get(int x1, int y1, int x2, int y2)

/** * 功能:記憶化搜尋

* @param x1 左上角x座標

* @param y1 左上角y座標

* @param x2 右下角x座標

* @param y2 右下角y座標

* @param k 剩餘的刀數

* @return 根據公式計算出的最小值

*/double dfs(int x1, int y1, int x2, int y2, int k)

//選擇縱著切

for (int i = y1; i < y2; i++)

//返回打擂台的最小值

return v;

}int main()

//利用二維字首和的結果,計算出平均值,注意要使用double的型別轉換,防止丟失精度

x = (double) s[m][m] / n;

//將dp陣列初始化為負無窮,計算過的》=0 (因為均方差可能為0),未計算過的為-inf

//方便獲取哪個位置是否計算過

memset(f, -0x3f, sizeof f);

//記憶化搜尋:因為最後需要切出n塊矩形棋盤,其實就是需要切n-1刀,開始dfs模擬切每一刀

printf("%.3lf\n", sqrt(dfs(1, 1, 8, 8, n - 1)));

return 0;

}

ACWing 321 棋盤分割

將乙個8 8 8 88 8的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了 n 1 n 1 n 1 次後,連同最後剩下的矩形棋盤共有n nn塊矩形棋盤。每次切割都只能沿著棋盤格仔的邊進行,例如下面的兩個圖,右圖裡中間豎著切一刀之後,不能繼續在左右...

F 棋盤分割

將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了 n 1 次後,連同最後剩下的矩形棋盤共有n塊矩形棋盤。每次切割都只能沿著棋盤格仔的邊進行 原棋盤上每一格有乙個分值,一塊矩形棋盤的總分為其所含各格分值之和。現在需要把棋盤按上述規則分割成n...

遞迴 棋盤分割問題

language default 棋盤分割 time limit 1000ms memory limit 10000k total submissions 11819 accepted 4175 description 將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩...