SP277 CTGAME - City Game 题解
前置知识
解法
令 \(f_{i,j}(1 \le i \le n,1 \le j \le m)\) 表示从 \((1,j)\) 到 \((i,j)\) 中以 \((i,j)\) 结尾的均为 F 的子串长度,即 \((i,j)\) 上面可延伸的最大距离(子矩形的长)。
用单调栈的第一维存储子矩形的长,第二维存储子矩形的宽。考虑依次枚举每一行和每一列,进行出入栈的操作。当枚举到 \((i,j)\) 的位置时,记录子矩形的宽 \(num\),有如下操作:
- 对于栈中原来的元素中大于当前的长 \(f_{i,j}\),要将其弹出栈,计数器 \(num\) 加 \(1\)。
- 子矩形的宽为弹出栈的元素个数。
 - 其所形成的子矩形面积为 $num \times $ 栈中当前的元素。
 
 - 将所得到的长 \(f_{i,j}\) 和宽 \(num\) 入栈。
 
代码
#include<bits/stdc++.h>
using namespace std;
int f[1001][1001];
int main()
{
    int n,m,t,v,i,j,ans,num;
    char pd;
    cin>>t;
    for(v=1;v<=t;v++)
    {
        ans=0;
        cin>>n>>m;
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                cin>>pd;
                if(pd=='F')
                {
                    f[i][j]=f[i-1][j]+1;
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            stack<pair<int,int>> s;
            s.push(make_pair(f[i][1],1));
            for(j=2;j<=m;j++)
            {
                num=0;
                while(s.empty()==0&&s.top().first>=f[i][j])
                {
                    num+=s.top().second;
                    ans=max(ans,num*s.top().first);
                    s.pop();
                }
                s.push(make_pair(f[i][j],num+1));
            }
            num=0;
            while(s.empty()==0)
            {
                num+=s.top().second;
                ans=max(ans,num*s.top().first);
                s.pop();
            }
        }
        cout<<ans*3<<endl;
    }
    return 0;
}
后记
多倍经验:P4147 | P5943 | UVA1330
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18011298,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。

                
            
        
浙公网安备 33010602011771号