切蛋糕
描述
有一块矩形蛋糕,宽和高分别是整数w、h。现要将其切成m块小蛋糕,每个小蛋糕都必须是矩形、且宽和高均为整数。切蛋糕时,每次切一块蛋糕,将其分成两个矩形蛋糕。请计算:最后得到的m块蛋糕中,最大的那块蛋糕的面积下限。
输入
共有多行,每行表示一个测试案例。
每行是三个用空格分开的整数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
难度
高,动态规划
解法
三维空间的填表法,每一刀要么横着切要么竖着切,将w*h的蛋糕分为m块可以看做切m-1刀。而切每一刀时又可分成已经切m-1刀的子问题。递归式为:
建立三维数组,largest [i] [j] [k],表示将i * j的蛋糕分为k+1块(切k刀)所得的最大面积;
k = 0 largest [i] [j] [k] = i*j
k+1 > i*J largest [i] [j] [k] =INF 切太多归与无穷
剩下情况枚举横切和竖切…
代码
#include <bits/stdc++.h>
using namespace std;
//largets[i][j][k]表示将i*j的蛋糕分为k+1块(切k刀)最大的那块蛋糕的面积下限
#define INF 0x3f3f3f3f //无穷
int main()
{
int l,w,m;
while(cin>>l>>w>>m && (l||w||m)){
int largets[l+1][w+1][m+1];
memset(largets,INF, sizeof(largets));
for(int i=0;i<=l;i++)
for(int j=0;j<=w;j++)
for(int k=0;k<=m;k++){
if(k==0)
largets[i][j][k]=i*j; //蛋糕不分时,本身最大
else if(i*j<k+1) //切的太多,不够分
largets[i][j][k]=INF;
else{
for(int r=1;r<i;r++) //横着切
for (int kk=0;kk<k;kk++) //剩下左边切几刀,右边切几刀,全部枚举
largets[i][j][k]=min(largets[i][j][k],max(largets[r][j][kk],largets[i-r][j][k-kk-1]));
for(int c=1;c<j;c++)//竖着切
for (int kk=0;kk<k;kk++) //左右切出来最大的面积,与当前最小值面积比较
largets[i][j][k]=min(largets[i][j][k],max(largets[i][c][kk],largets[i][j-c][k-kk-1]));
}
}
cout<<largets[l][w][m-1]<<endl;
}
}