思路:
动态规划
dp[w][h][m] = 宽为w,高为h的蛋糕切m刀后最大快蛋糕面积的下限
递推公式:
dp[w][h][m] = min(切的第一刀为横的最优解,切的第一刀为竖的最优解)
切的第一刀为横的最优解 = min(s(i))(1<=i<=h-1)
(s(i)表示切完第一刀后上边的蛋糕的高度为i的情况的最优解)
切完第一刀后上边的蛋糕的高度为i的情况的最优解 =
min(max(dp[w][i][k]),dp[w][h-i][m-k])(k表示分配到上面的蛋 糕的刀数)
以此类推
dp数组生成顺序:
h从小到达生成
w,h应该可以任意顺序(未验证)
#include <cstdio>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f;
using namespace std;
int w,h,m;
int dp[30][30][30];
//已经切成了两块蛋糕,分配剩余的刀数
int sx(int i1,int j1,int i2,int j2,int k){
//按前一个蛋糕分配的刀数分为几种情况
int d;
int res;
for(d=0;d<=k;d++){
if(d==0){
res = max(dp[i1][j1][d],dp[i2][j2][k-d]);
}else{
res = min(res,max(dp[i1][j1][d],dp[i2][j2][k-d]));
}
}
return res;
}
//横着切时的情况,分配上下两块蛋糕的高度
int s1(int i,int j,int k){
int l;
int res;
//按上边的蛋糕的高度分为几种情况
for(l=1;l<j;l++){
if(l==1){
res = sx(i,l,i,j-l,k-1);
}else{
res = min(res,sx(i,l,i,j-l,k-1));
}
}
return res;
}
//竖着切的时候,分配左右两块蛋糕的宽度
int s2(int i,int j,int k){
int l;
int res;
//按左边的蛋糕的宽度分为几种情况
for(l=1;l<i;l++){
if(l==1){
res = sx(l,j,i-l,j,k-1);
}else{
res = min(res,sx(l,j,i-l,j,k-1));
}
}
return res;
}
int ans[1000];
int ans2[1000];
int v = 0;
int main() {
cin>>w>>h>>m;
while(w!=0||h!=0||m!=0){
//边界条件
int i,j,k;
for(i=1;i<=w;i++){
for(j=1;j<=h;j++){
dp[i][j][0] = i*j;
}
}
//通过递推得到dp
for(k=1;k<=m-1;k++){
for(i=1;i<=w;i++){
for(j=1;j<=h;j++){
if(i*j>k){
if(i>1&&j>1){
dp[i][j][k] = min(s1(i,j,k),s2(i,j,k));
}else if(i>1&&j==1){
dp[i][j][k] = s2(i,j,k);
}else if(i==1&&j>1){
dp[i][j][k] = s1(i,j,k);
}
}
}
}
}
// for(k=0;k<=m-1;k++){
// for(i=1;i<=w;i++){
// for(j=1;j<=h;j++){
// cout<<i<<" "<<j<<" "<<k<<" "<<dp[i][j][k]<<endl;
// }
// }
// }
// ans[v] = dp[w][h][m-1];
// v++;
cout<<dp[w][h][m-1]<<endl;
cin>>w>>h>>m;
}
// int i;
// for(i=0;i<v;i++){
// cin>>ans2[i];
// }
// for(i=0;i<v;i++){
// cout<<i<<" "<<ans[i]<<" "<<ans2[i]<<endl;
// }
return 0;
}