• 【专题】矩形和正方形的最大面积


    一.矩形的最大面积——单调栈

    (1)例题

    P4147 玉蟾宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    (2)讲解(摘自题解)

    问题转化:

    • n行m列土地,求最大矩形面积,我们把问题拆分成n个子问题来解决.

    • 对于每一行,依次记录每行向上一直是F土地的可延伸的最大距离,记为f(i,j).

      1. 当前元素(i,j)为F,则f(i,j)=f(i-1,j)+1.
      2. 当前元素(i,j)为R,则f(i,j)=0.
    • 我们记录这个数组有什么用呢?这就可以转化为单调栈维护的问题了.

    具体思路:

    • 对于每一个子问题,我们维护一个单调递增的单调栈.我们定义一个结构体(其中记录的两个元素分别是当前行第j个矩形的f值,以及它在当前已加入栈中矩形高度的排名).

    • 我们考虑当前加入第k个矩形的情况.

      1. 当前矩形高度大于栈顶,直接加入即可,因为没有比它大的元素,那么他的排名为1.

      2. 当前矩形高度小于栈顶,则不断取出栈顶,直到栈为空或者栈顶矩形的高度比当前矩形小.在出栈过程中,我们累计被弹出的矩形的宽度之和,并且每弹出一个矩形,就用它的高度乘上累计的排名(是累计,因为在它入栈后还有比它大的元素入栈)来更新答案.

      3. 这样为什么是对的呢?这是因为:如果当前要加入矩形的f值(即当前矩形的高度比上一个小),那么该矩形想利用前面的矩形一起构成一个大矩形是,这块矩形的高度不可能超过该矩形自己的高度,则记录前面元素的高度就没有用处了.而宽度还有用处(因为当前矩形高度较小,与比它高的矩形的宽度总和相乘,在此矩形出栈时,要用它来更新答案).所以我们要记一个当前已加矩形的高度排名(无论是在栈里还是已经出栈).而又因为每个元素只被弹栈一次,所以不会有重复情况.

      4. 在所有矩形(m个)都考虑过后,我们再用还没有弹栈的元素再来个新一波答案,直到栈空

    (3)AC

    1. #include
    2. #define maxn 1005
    3. using namespace std;
    4. int n,m;
    5. int ans,maxs;
    6. struct node{
    7. int hign,length;
    8. }sta[maxn];
    9. int f[maxn][maxn]; //记录每行每列的高
    10. void work(int x){
    11. int top=1,len=0;
    12. maxs=0;
    13. sta[top].hign=f[x][1];
    14. sta[top].length=1;
    15. for(int i=2;i<=m;i++){
    16. len=0;
    17. //维持递增
    18. while(sta[top].hign>=f[x][i] && top>0){
    19. len+=sta[top].length; //继承长度,毕竟高的可以,低的也必可以
    20. maxs=max(maxs,sta[top--].hign*len);
    21. }
    22. sta[++top].hign=f[x][i];
    23. sta[top].length=len+1;
    24. }
    25. len=0;
    26. //同上while
    27. while(top){
    28. len+=sta[top].length;
    29. maxs=max(maxs,sta[top--].hign*len);
    30. }
    31. ans=max(ans,maxs);
    32. }
    33. int main(){
    34. scanf("%d%d",&n,&m);
    35. char c;
    36. for(int i=1;i<=n;i++){
    37. for(int j=1;j<=m;j++){
    38. cin>>c;
    39. if(c=='F') f[i][j]=f[i-1][j]+1;
    40. }
    41. }
    42. //枚举每一行,解决子问题
    43. for(int i=1;i<=n;i++) work(i);
    44. printf("%d",ans*3);
    45. return 0;
    46. }

    二.正方形的最大面积——dp

    (1)例题

    P1387 最大正方形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    (2)讲解

    就是一个简单的dp,dp状态转移方程式为:

    dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;

    (3)AC

    1. #include
    2. #define maxn 101
    3. using namespace std;
    4. int n,m;
    5. int a[maxn][maxn],dp[maxn][maxn];
    6. int ans;
    7. int main(){
    8. cin>>n>>m;
    9. for(int i=1;i<=n;i++)
    10. for(int j=1;j<=m;j++)
    11. scanf("%d",&a[i][j]);
    12. for(int i=1;i<=n;i++){
    13. for(int j=1;j<=m;j++){
    14. if(a[i][j]==1){
    15. dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
    16. }
    17. ans=max(ans,dp[i][j]);
    18. }
    19. }
    20. cout<
    21. }

  • 相关阅读:
    分布式共识算法
    算法篇:查找算法
    变量、流程控制与游标20221027
    Ubuntu服务器的GitLab部署
    HTML5、CSS3面试题(三)
    LLMOps快速入门,轻松开发部署大语言模型
    高德地图获取行政区域并且获取经纬度
    【vector题解】连续子数组的最大和 | 数组中出现次数超过一次的数字
    VBA技术资料MF72:利用函数判断文件及工作表存在
    Docker 网络管理及资源控制
  • 原文地址:https://blog.csdn.net/qq_49705495/article/details/133787312