POJ 2951 Cake Cutting(动态规划)

本文探讨了如何将一个矩形蛋糕通过指定数量的直线切割分成多个矩形部分,使得最大的那块面积尽可能小。采用记忆化搜索和动态规划的方法,通过枚举切割的方向和位置来寻找最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description


You are given a rectangular cake of integral dimensions w × h. Your goal is to divide this cake into m rectangular pieces of integral dimensions such that the area of the largest piece is minimal. Each cut must be a straight line parallel to one of the sides of the original cake and must divide a piece of cake into two new pieces of positive area. Note that since a cut divides only a single piece, exactly m−1 cuts are needed.


Examples


If w = 4, h = 4, and m = 4, then the following cuts minimize the area of the largest piece:



However, if w = 4, h = 4, and m = 3, then the following cuts are optimal:



Input


The input test file will contain multiple test cases, each of which consists of three integers w, h, m separated by a single space, with 1 <= w, h,m <= 20 and m <= wh. The end-of-file is marked by a test case with w = h = m = 0 and should not be processed.


Output


For each test case, write a single line with a positive integer indicating the area of the largest piece.


Sample Input

4 4 4
4 4 3
0 0 0




Sample Output

4
6


总之要想办法构造出状态转移方程,这道题是:

记忆化搜索,dp[k][i][j]为将一块i*j的蛋糕切k刀的最大面积的最小值,枚举下一刀的横竖以及切的位置和其中一份的刀数

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int dp[405][25][25];
int dfs(int m,int w,int h)
{
    if(dp[m][w][h]!=inf)
        return dp[m][w][h];
    else if(m==0)
        return dp[m][w][h]=w*h;
    else
    {
        int ans=inf;
        for(int i=1,lim=w/2+1;i<=lim;i++)
            for(int k=0;k<=m-1;k++)
                ans=min(ans,max(dfs(k,i,h),dfs(m-1-k,w-i,h)));
        for(int i=1,lim=h/2+1;i<=lim;i++)
            for(int k=0;k<=m-1;k++)
                ans=min(ans,max(dfs(k,w,i),dfs(m-1-k,w,h-i)));
        return dp[m][w][h]=ans;
    }
}
int main()
{
    int w,h,m;
    memset(dp,0x3f,sizeof(dp));
    while(scanf("%d%d%d",&w,&h,&m),w||h||m)
        printf("%d\n",dfs(m-1,w,h));
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值