NOI 4.5 動態規劃 6047:分蛋糕(列舉)
阿新 • • 發佈:2019-01-04
6047:分蛋糕
總時間限制: 1000ms 記憶體限制: 65536kB
描述
有一塊矩形大蛋糕,長和寬分別是整數w、h。現要將其切成m塊小蛋糕,每個小蛋糕都必須是矩形、且長和寬均為整數。切蛋糕時,每次切一塊蛋糕,將其分成兩個矩形蛋糕。請計算:最後得到的m塊小蛋糕中,最大的那塊蛋糕的面積下限。
假設w= 4, h= 4, m=4,則下面的切法可使得其中最大蛋糕塊的面積最小:
假設w= 4, h=4, m= 3,則下面的切法會使得其中最大蛋糕塊的面積最小:
輸入
共有多行,每行表示一個測試案例。每行是三個用空格分開的整數w, h, m ,其中1 ≤ w, h, m ≤ 20 ,m ≤ wh. 當 w = h = m = 0
輸出
每個測試案例的結果佔一行,輸出一個整數,表示最大蛋糕塊的面積下限。
樣例輸入
4 4 4
4 4 3
0 0 0
樣例輸出
4
6
-----------------------------------------------------
思路
dp[i][j][k]: 長為i,寬為j的矩形切k刀得到的最大塊的面積下界
列舉豎切、橫切的所有情況找最小的最大值即可
由於有多組輸入(大的輸入的計算過程會覆蓋小的輸入的計算過程導致重複計算),總的情況又不是很多(1<=w,h,m<=20, m<=w*h),因此直接計算出所有情況的答案,以後讀入輸入只要去dp數組裡查就可以了。
-----------------------------------------------------
程式碼
//動態規劃 #include<iostream> #include<cstring> #include<climits> using namespace std; const int INF = 1000000000; int dp[25][25][25] = {}; // 長為i,寬為j的矩形切k刀最大塊的面積下界 int main() { int w,h,m,i1,i2,i3,i4,i5; // 預先把所有可能(1~20)的情況都計算出來 memset(dp,0x3f,sizeof(dp)); for (i1=1; i1<=20; i1++) { for (i2=1; i2<=20; i2++) { dp[i1][i2][1] = i1*i2; } } for (i1=1; i1<=20; i1++) { for (i2=1; i2<=20; i2++) { for (i3=2; i3<=min(20, i1*i2); i3++) { for (i4=1; i4<i1; i4++) { for (i5=1; i5<i3; i5++) { dp[i1][i2][i3] = min(dp[i1][i2][i3], max(dp[i4][i2][i5], dp[i1-i4][i2][i3-i5])); // 豎著切 } } for (i4=1; i4<i2; i4++) { for (i5=1; i5<i3; i5++) { dp[i1][i2][i3] = min(dp[i1][i2][i3], max(dp[i1][i4][i5], dp[i1][i2-i4][i3-i5])); // 橫著切 } } } } } // 輸入了只要直接O(1)訪問輸出就行了 while (cin >> w >> h >> m) { if (w==0) { break; } cout << dp[w][h][m] << endl; } return 0; }