嘘~ 正在从服务器偷取页面 . . .

SP277 CTGAME - City Game 题解


SP277 CTGAME - City Game 题解

题目链接:CTGAME - City Game

题意

鲍伯是一个战略游戏编程专家。在他的新城市建设游戏中,游戏环境如下:城市是由街道、树木、工厂和建筑物组成的区域。这个地区还没有空余的空间。他的游戏的战略任务是从这些自由空间中赢得尽可能多的租金。要赢得租金,你必须竖立建筑物,它只能是长方形的,尽可能长和宽。鲍伯正试图找到一种方法来建造每一个地区最大的建筑。但是他遇到了一些问题——他不被允许破坏他正在建设的地区已经存在的建筑物、树木、工厂和街道。

每个区域都有其宽度和长度。该地区被划分为等格子单位,你所建单位的租金为 3 美元。

你的任务是帮助鲍伯解决这个问题。整个城市分为K区。每个区域都是矩形的,并且具有不同的网格大小,其长度M和宽度N不同。现有的占用单元用符号R标记。未占用单元用符号F标记。

输入格式

The first line of the input contains an integer K - determining the number of datasets. Next lines contain the area descriptions. One description is defined in the following way: The first line contains two integers-area length M<=1000 and width N<=1000, separated by a blank space. The next M lines contain N symbols that mark the reserved or free grid units,separated by a blank space. The symbols used are:

R - reserved unit

F - free unit

In the end of each area description there is a separating line.

输出格式

For each data set in the input print on a separate line, on the standard output, the integer that represents the profit obtained by erecting the largest building in the area encoded by the data set.

这个题目翻译确实很难懂

其实就是问你每个联通块里最大的矩形有多大,并输出所有这样矩形的价值和

感觉自己的思路还是不够清晰,仅仅是去想这样的矩形会是什么样子的并且如何框出来这样的矩形。

注意到这个联通块实际上“横平竖直”,也就是当我们确定一个底边的位置时,它的高我们就确定了。

假设我们确定第 \(i\) 行的 \([l,r]\) 作为底边(前提是 \([l,r]\) 合法),那么它的高就是 \([l,r]\)\(\mathtt{F}\) 最矮的那一个。

于是考虑处理每个 \(\mathtt{F}\) 点上方相连的 \(\mathtt{F}\) 的个数(包含自身),然后枚举行 \(i\)

此时问题就转化为了,在一个序列中找到这样的一个矩形,也就是题 HISTOGRA ,可以用单调栈解决

时间复杂度 \(\mathcal{O}(nm)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
typedef pair<int,int> pii;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e3 + 15))
#define Fi first
#define Se second

int n, m, c[N][N];
pii stk[N]; char a[N][N];
int proc(int x)
{
    int top = 0, res = 0;
    for(int i = 1; i <= m + 1; i++)
    {
        if(top < 1 || c[x][i] > stk[top].Fi) { stk[++top] = {c[x][i], 1}; }
        else
        {
            int w = 0;
            while(top > 0 && c[x][i] < stk[top].Fi)
            {
                w += stk[top].Se; up(res, w * stk[top].Fi);
                --top;
            }
            stk[++top] = {c[x][i], w + 1};
        }
    }
    return res;
}
void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            cin >> a[i][j];
            if(a[i][j] == 'F') c[i][j] = c[i - 1][j] + 1; else c[i][j] = 0;
        }
    int res = 0;
    for(int i = 1; i <= n; i++) up(res, proc(i));
    cout << res * 3 << '\n';
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int qwq; cin >> qwq; while(qwq--) solve();
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/article/jqsnl8iz


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录