思维模拟+暴力——icpc nwrrc 2019 K

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了思维模拟+暴力——icpc nwrrc 2019 K相关的知识,希望对你有一定的参考价值。

这题思路上不是很难,但是写起来贼复杂(知道为什么没啥人过了)

其实这题难的不是A的面积有多大,而是确定A后怎么填充剩下的矩形

自己写的代码复制粘贴三百多行,贴上题解的得了

题解用拉伸的填充法把代码化简了好多。。

如果不需要最大化矩形A的面积,则可以用如下算法解决该问题。垂直拉伸每个字母,直到碰到另一个字母或王国的边界。这样,我们得到了一组完整的列。水平拉伸每一列,直到碰到另一个字母或王国的边界。

考虑如何最大化矩形A的面积。首先,找到包含字母A且不包含其他字母的最大面积的矩形。这是一个经典问题。

显然王国的其余部分仍可以按要求的方式分成矩形。因为我们可以将剩下的区域分为四个大矩形:矩形的A上,下,左,右侧(左上,左下,右上,右下可并到任意一个相邻的大矩形中)。

每个大矩形都包含至少一个字母(否则我们可以在相应的方向上放大矩形A)。对于剩下的四个大矩形分别采取最开始的算法即可。

技术图片
#include <bits/stdc++.h>

#define long long long int

using namespace std;

// @author: pashka

void fill(vector<string> &a, int U, int B, int L, int R, char c) {
    for (int i = U; i < B; i++) {
        for (int j = L; j < R; j++) {
            a[i][j] = c;
        }
    }
}

char lower(char c) {
    if (c >= A && c <= Z) {
        c = a + (c - A);
    }
    return c;
}

void split(vector<string> &a, int U, int B, int L, int R) {
    for (int i = U + 1; i < B; i++) {
        for (int j = L; j < R; j++) {
            if (a[i][j] == .) {
                a[i][j] = lower(a[i - 1][j]);
            }
        }
    }
    for (int i = B - 2; i >= U; i--) {
        for (int j = L; j < R; j++) {
            if (a[i][j] == .) {
                a[i][j] = lower(a[i + 1][j]);
            }
        }
    }
    for (int i = U; i < B; i++) {
        for (int j = L + 1; j < R; j++) {
            if (a[i][j] == .) {
                a[i][j] = lower(a[i][j - 1]);
            }
        }
    }
    for (int i = U; i < B; i++) {
        for (int j = R - 2; j >= L; j--) {
            if (a[i][j] == .) {
                a[i][j] = lower(a[i][j + 1]);
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);

    int n, m;
    cin >> n >> m;
    vector<string> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];

    int ar = -1, ac = -1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (a[i][j] == A) {
                ar = i;
                ac = j;
            }
        }
    }
    a[ar][ac] = .;

    int maxS = -1;
    int bestL = -1;
    int bestR = -1;
    int bestU = -1;
    int bestB = -1;
    vector<int> up(m + 1);
    for (int i = 0; i < n; i++) {
        vector<pair<int, int>> s;
        for (int j = 0; j <= m; j++) {
//            cout << i << " " << j << "
";
            if (j == m || a[i][j] != .) {
                up[j] = i + 1;
            }
            int x = j;
            while (!s.empty() && s.back().second < up[j]) {
                int L = s.back().first;
                int R = j;
                int U = s.back().second;
                int B = i + 1;
                if (U <= ar && ar < B && L <= ac && ac < R) {
                    int S = (R - L) * (B - U);
                    if (S > maxS) {
                        maxS = S;
                        bestL = L;
                        bestR = R;
                        bestU = U;
                        bestB = B;
                    }
                }
                x = s.back().first;
                s.pop_back();
            }
            s.push_back({x, up[j]});
        }
    }
//    cout << bestU << " " << bestB << " " << bestL << " " << bestR << "
";
    fill(a, bestU, bestB, bestL, bestR, a);

    split(a, 0, bestU, 0, m);
    split(a, bestB, n, 0, m);
    split(a, bestU, bestB, 0, bestL);
    split(a, bestU, bestB, bestR, m);

    a[ar][ac] = A;

    for (int i = 0; i < n; i++) {
        cout << a[i] << "
";
    }

    return 0;
}
View Code

 

以上是关于思维模拟+暴力——icpc nwrrc 2019 K的主要内容,如果未能解决你的问题,请参考以下文章

2019ACM-ICPC沈阳网络赛-K-Guanguan's Happy water(思维+暴力)

2020年2月2日 ICPC2019徐州 现场赛C <3 numbers 思维题

2019 ICPC南京站 B题 Chessboard组合数,乘法逆元

ICPC2019南昌区域赛

2019icpc银川网络赛-A Maximum(思维)

思维数学+treap——icpc 2019 nwerc