动态规划实战练习3-分蛋糕
原题摘录-初步分析
通读之后,大致意思就是将一个矩形蛋糕切成有限个矩形小蛋糕,给定你长宽和切之后小蛋糕的块数,让你找到一种切法,使得m块小蛋糕中最大的那块蛋糕的底面积(朝向我们的)最小.
仔细阅读-进一步理解题意
第二遍读题,更深入的理解问题,其实就是获得更加细节的问题.什么教最大块的最小面积.就是我们要先算出所有切法中对应的那块最大蛋糕.然后再在这些已经选出的蛋糕里选出底面积最小的.
决胜之战-确定数据结构和算法
到了这里,相信不用看题目,别人问你这个题的意思,也能给他以自己的理解方式复述一遍.
在这个问题里,显然不需要什么特殊的数据结构.
因为每一次切蛋糕,横切和竖切都具有相似性.就拿竖切来说,每一次切,是不是都造成一个结果:那就是蛋糕被分成左右两部分.所以说你只需要枚举出这一次下刀左部分的宽度,那右部分不就是总宽度-左宽.左边切k刀,右边不就是切总数-k.
要求宽为w,高为h的蛋糕切成m小块的最大最小面积
切成m个小块就是切了m-1刀,不就是求ways(W,H,M-1).
假设ways(W,H,M-1)为W,宽为H,被切M-1刀后,最大的那块蛋糕的面积最小值 .
显然这里有三个变量表征状态,所有用三维数组来搜索记忆.
继续找状态方程:
看到这里,可能会好奇求Si那一步为什么要求max(),ways不是已经代表的是最大最小面积了吗?这个时候请回到仔细阅读-进一步理解题意.也就是说在一种切法里求的是最大值.然后在所有切法里求最小值.
编写主要代码-搭好框架
int solve(int w,int h,int m){
if(w*h<m+1) return INF;//当前面积无法切m刀
if(m==0) return w*h;//不需要切了,出口
if(ways[w][h][m]!=-1) return ways[w][h][m];//已访问过
int mx=INF;
for(int i=1;i<=w-1;++i){//枚举第一刀竖着切的各种切法,只是第一刀,左边宽为i的最好结果
for(int k=0;k<=m-1;++k){//枚举左边的切法
int m1=solve(i,h,k);//左边切了k刀得到的最大面积的最小值
int m2=solve(w-i,h,m-1-k);//右边切入m-1-k刀...
mx=min(mx,max(m1,m2));
}
}
for(int i=1;i<=h-1;++i){//枚举第一刀横着切的各种切法,只是第一刀
for(int k=0;k<=m-1;++k){//枚举上边的切法
int m1=solve(w,i,k);//上边切了k刀得到的最大面积的最小值
int m2=solve(w,h-i,m-1-k);//下边切入m-1-k刀...
mx=min(mx,max(m1,m2));
}
}
ways[w][h][m]=mx;
return mx;
}
如果还有不理解的地方,可在下方评论区留言,会在看到后第一时间回复.手打不易,在线求赞!