- Description
-
有一块矩形大蛋糕,长和宽分别是整数w 、h。现要将其切成m块小蛋糕,每个小蛋糕都必须是矩形、且长和宽均为整数。切蛋糕时,每次切一块蛋糕,将其分成两个矩形蛋糕。请计算:最后得到的m块小蛋糕中,最大的那块蛋糕的面积下限。
假设w= 4, h= 4, m= 4,则下面的切法可使得其中最大蛋糕块的面积最小。
假设w= 4, h= 4, m= 3,则下面的切法会使得其中最大蛋糕块的面积最小:
- Input
- 共有多行,每行表示一个测试案例。每行是三个用空格分开的整数w, h, m ,其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 当 w = h = m = 0 时不需要处理,表示输入结束。
- Output
- 每个测试案例的结果占一行,输出一个整数,表示最大蛋糕块的面积下限。
- Sample Input
-
4 4 44 4 30 0 0
- Sample Output
-
46
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int MAXN = 30; const int INF = (2L << 30) - 2; int dp[MAXN][MAXN][MAXN]; int ways(int w, int h, int m);//用ways()来表示对宽为w, 高为h的矩形,切m刀,得到的最大矩形的最小面积 int main() { int W, H, M; while(cin >> W >> H >> M){ if(W == 0 && H == 0 && M == 0) break; memset(dp, -1, sizeof(dp));//初始化dp数组所有元素的值为-1 cout << ways(W, H, M - 1) << endl; } return 0; } int ways(int w, int h, int m) { if(dp[w][h][m] != -1)//如果dp[]的值不为-1,则说明当前状态已经被计算过一次了,就不需要再重复计算了 return dp[w][h][m];//直接返回当前dp[]值 if(w * h < m + 1)//如果说w * h < m + 1就说明这个状态是无意义的 return dp[w][h][m] = INF;//设置已被计算过,并且返回无意义值INF if(m == 0)//一刀也不切的话,这块矩阵的面积就为w * h return dp[w][h][m] = w * h; int SV = INF;//shear切, vertical表示竖着切, horizental表示横着切. int SH = INF;//SV和SH是并行的,是不同的决策. for(int i = 1; i < w; ++i)// 第一刀竖着切 for(int j = 0; j < m; ++j)//不同的j也属于不同的决策.SV保存这这种不同的决策的较小者 SV = min(SV, max(ways(i, h, j), ways(w - i, h, m - 1 - j))); //这里是需要注意的点, max(ways(i, h, j), ways(w - i, h, m - 1 - j))得到的是 //能得到的是这两块分好的矩阵里,较大面积下限(最小值).因为这才是真正的最大面积的最小值 //所以SV要取所有的切法得到的最大面积的最小下限的最小值. for(int i = 1; i < h; ++i)// 第一刀横着切 for(int j = 0; j < m; ++j) SH = min(SH, max(ways(w, i, j), ways(w, h - i, m - 1 - j))); return dp[w][h][m] = min(SH, SV);//返回不同的决策得到的最优的解. }
分蛋糕
猜你喜欢
转载自blog.csdn.net/u013482363/article/details/78987765
今日推荐
周排行