6047:分蛋糕
题目链接http://noi.openjudge.cn/ch0405/6047/
思路: 无后效性,小为大搭建积木
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[25][25][25];//dp[i][j][k],为i*j的蛋糕切成k块,满足的最优值
int w, h, m;
//其中1 ≤ w, h, m ≤ 20 , m ≤ wh. 当 w = h = m = 0 时不需要处理,表示输入结束。
void solve() {
memset(dp, 0x3f, sizeof(dp));
for (int i = 1; i <= 20; i++) {
for (int j = 1; j <= 20; j++) {
for (int k = 1; k <= min(20,i*j); k++) {
if (k == 1) {//一块,填上原始大小即可
dp[i][j][k] = i * j;
continue;
}
if (i * j< k) {//无法分配k块(剪枝)
continue;
}
for (int z = 1; z < i; z++) {//竖切
for (int zz = 1; zz < k; zz++) {
if (z * j< zz || (i - z) * j < (k - zz))
continue; //无法分配(剪枝)
dp[i][j][k] = min(dp[i][j][k], max(dp[z][j][zz], dp[i - z][j][k-zz]));
}
}
for (int z = 1; z < j; z++) {//横切
for (int zz = 1; zz < k; zz++) {
if (z * i < zz || (j - z) * i < (k - zz))
continue; //无法分配(剪枝)
dp[i][j][k] = min(dp[i][j][k], max(dp[i][z][zz], dp[i ][j-z][k - zz]));
}
}
}
}
}
}
int main() {
solve();
while (cin >> w >> h >> m) {
if (w == 0 && h == 0 && m == 0)
break;
printf("%d\n", dp[w][h][m]);
}
return 0;
}