OpenJudge 6047 Split Cake (dp)

description

There is a large rectangular cake whose length and width are integers w and h respectively. Now we are going to cut it into m pieces of small cakes. Each small cake must be rectangular, and the length and width must be integers. When cutting the cake, cut a piece of cake at a time and divide it into two rectangular cakes. Please calculate: the lower limit of the area of ​​the largest piece of cake among the m pieces of small cakes finally obtained.

Assuming w= 4, h= 4, m= 4, the following cutting method can minimize the area of ​​the largest cake piece.
Insert picture description here

Assuming w= 4, h= 4, m= 3, the following cutting method will minimize the area of ​​the largest cake piece:

Insert picture description here

enter

There are multiple lines, and each line represents a test case. Each line is three integers w, h, m separated by spaces, where 1 ≤ w, h, m ≤ 20 and m ≤ wh. When w = h = m = 0, no processing is required, indicating the end of input.

Output

The result of each test case occupies one line, and an integer is output to indicate the lower limit of the area of ​​the largest cake piece.

Sample input

4 4 4
4 4 3
0 0 0

Sample output

4
6

Ideas

f[i][j][k] means that the cake with length i and width j is divided into the largest volume in k pieces. It can be divided into two parts, and then one part is divided into p pieces, and the other part is divided into two parts. It is kp block. Note that it can be divided horizontally. It can also be divided vertically, whichever is the smallest.

Code

#include<iostream>
#define inf 0x3f3f3f
using namespace std;

int f[22][22][22];								//f[i][j][k]表示将长为i宽为j的蛋糕分为k块中的最大体积

int main()
{
    
    
	int w,h,m;
	w=h=m=20;									//因为是多次输入,可以先将所有数据跑一遍 
	for(int i=1;i<=w;i++)						//长 
	{
    
    
		for(int j=1;j<=h;j++)					//宽 
		{
    
    
			f[i][j][1]=i*j;						//分一块,最大就是自己 
			for(int k=2;k<=m&&k<=i*j;k++)		//分两块以上  分k块 
			{
    
    
				f[i][j][k]=inf;					//初始为最大 
				for(int r=1;r<i;r++)			//横着先将其分为两部分  枚举切的位置 
					for(int p=1;p<k;p++)		//剩下的分为 p块和k-p块 取最小的分法 
						f[i][j][k]=min(f[i][j][k],max(f[r][j][p],f[i-r][j][k-p]));
				for(int c=1;c<j;c++)			//第一刀,竖着分 
					for(int p=1;p<k;p++)
						f[i][j][k]=min(f[i][j][k],max(f[i][c][p],f[i][j-c][k-p]));
			}
		}
	}
	while(1)
	{
    
    
		cin>>w>>h>>m;
		if(w==0)
			return 0;
		cout<<f[w][h][m]<<endl;
	}
}

Guess you like

Origin blog.csdn.net/m0_54621932/article/details/114013262