分蛋糕

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