Loading

Gym-102411K

K - King's Children

题意

给一个矩形, 矩形里有一些不同的字母,其他都是空地,每个字母会占据一个矩形区域,要求构造一种方案,把所有的空地都划分掉,并且使 'A' 所占的区域面积最大

思路

第一步, 找 A 的最大矩形

先找到 'A' 的最大矩形,我们可以这样做, 先把 'A' 所在的地方进行列上的扩展, 设 'A' 的坐标是 (x, y)

设两个数组 l[N], r[N]。 l[row] 表示以 (x, y) 和 (row, y) 作为底边,最多能向左边扩展多少个单位长度, r[row] 表示以 (x, y) 和 (row, y) 作为底边, 最多向右扩展多少个单位长度。

这样, 我们可以枚举这个矩形的上界 up 和下界 down

则这个矩形的高是 down - up + 1 , 长是 (min(l[up], l[down]) + min(r[up], r[down]) + 1)

第二步, 完成剩余字母的合法构造

如果用第一步的方法去填剩下的字母, 可能无法填完所有的空位。

把剩下的区域分成如下四个部分

对于绿色部分,可以按列填充,对于每一个字母,尽可能的向向下扩充,若一列都没有字母,则向 'A' 方向的列进行复制。

蓝色的部分,进行按行填充。

这样能保证构造出一个合法的方案。

/*
 * @Author: zhl
 * @LastEditTime: 2021-03-02 21:31:19
 */

#include<bits/stdc++.h>
using namespace std;

const int N = 1e3 + 10;
typedef long long ll;
int n, m;

char mp[N][N];
int l[N], r[N];

void solve(int x, int y) {
    char c = mp[x][y] - 'A' + 'a';
    for (int i = 1;i <= n;i++)l[i] = r[i] = 0;

    for (int i = x;i <= n;i++) {
        if (i != x and mp[i][y] != '.')break;
        while (y + r[i] + 1 <= m and mp[i][y + r[i] + 1] == '.')r[i]++;
        while (y - l[i] - 1 >= 1 and mp[i][y - l[i] - 1] == '.')l[i]++;
        if (i != x)l[i] = min(l[i], l[i - 1]), r[i] = min(r[i], r[i - 1]);
    }
    for (int i = x - 1;i >= 1;i--) {
        if (mp[i][y] != '.')break;
        while (y + r[i] + 1 <= m and mp[i][y + r[i] + 1] == '.')r[i]++;
        while (y - l[i] - 1 >= 1 and mp[i][y - l[i] - 1] == '.')l[i]++;
        l[i] = min(l[i], l[i + 1]), r[i] = min(r[i], r[i + 1]);
    }
    int up, down, now = l[x] + r[x] + 1;
    up = down = x;
    for (int i = x;i >= 1;i--) {
        if (i != x and mp[i][y] != '.')break;
        for (int j = x;j <= n;j++) {
            if (j != x and mp[j][y] != '.')break;
            int S = (min(l[i], l[j]) + min(r[i], r[j]) + 1) * (j - i + 1);
            if (S > now) {
                now = S;up = i;down = j;
            }
        }
    }

    for (int i = up;i <= down;i++) {
        for (int j = y - min(l[up], l[down]);j <= y + min(r[up], r[down]);j++) {
            if (i != x or j != y)mp[i][j] = c;
        }
    }

    for (int j = y - min(l[up], l[down]) - 1;j >= 0;j--) {
        int cnt = 0;
        for (int i = 1;i <= n;i++) {
            if (mp[i][j] > 'A' and mp[i][j] <= 'Z') {
                char c = mp[i][j] - 'A' + 'a';
                int k = 1;
                while (i - k >= 1 and mp[i - k][j] == '.')mp[i - k][j] = c, k++;
                k = 1;
                while (i + k <= n and mp[i + k][j] == '.')mp[i + k][j] = c, k++;
                cnt++;
            }
        }
        if (cnt == 0) {
            for (int i = 1;i <= n;i++)mp[i][j] = tolower(mp[i][j + 1]);
        }
    }

    for (int j = y + min(r[up], r[down]) + 1;j <= m;j++) {
        int cnt = 0;
        for (int i = 1;i <= n;i++) {
            if (mp[i][j] > 'A' and mp[i][j] <= 'Z') {
                char c = mp[i][j] - 'A' + 'a';
                int k = 1;
                while (i - k >= 1 and mp[i - k][j] == '.')mp[i - k][j] = c, k++;
                k = 1;
                while (i + k <= n and mp[i + k][j] == '.')mp[i + k][j] = c, k++;
                cnt++;
            }
        }
        if (cnt == 0) {
            for (int i = 1;i <= n;i++)mp[i][j] = tolower(mp[i][j - 1]);
        }
    }

    for (int i = up - 1;i >= 1;i--) {
        int cnt = 0;
        for (int j = y - min(l[up], l[down]);j <= y + min(r[up], r[down]);j++) {
            if (mp[i][j] > 'A' and mp[i][j] <= 'Z') {
                char c = mp[i][j] - 'A' + 'a';
                int k = 1;
                while (j - k >= y - min(l[up], l[down]) and mp[i][j - k] == '.')mp[i][j - k] = c, k++;
                k = 1;
                while (j + k <= y + min(r[up], r[down]) and mp[i][j + k] == '.')mp[i][j + k] = c, k++;
                cnt++;
            }
        }
        if(cnt == 0){
            for (int j = y - min(l[up], l[down]);j <= y + min(r[up], r[down]);j++) mp[i][j] = tolower(mp[i + 1][j]);
        }
    }

    for (int i = down + 1;i <= n;i++) {
        int cnt = 0;
        for (int j = y - min(l[up], l[down]);j <= y + min(r[up], r[down]);j++) {
            if (mp[i][j] > 'A' and mp[i][j] <= 'Z') {
                char c = mp[i][j] - 'A' + 'a';
                int k = 1;
                while (j - k >= y - min(l[up], l[down]) and mp[i][j - k] == '.')mp[i][j - k] = c, k++;
                k = 1;
                while (j + k <= y + min(r[up], r[down]) and mp[i][j + k] == '.')mp[i][j + k] = c, k++;
                cnt++;
            }
        }
        if (cnt == 0) {
            for (int j = y - min(l[up], l[down]);j <= y + min(r[up], r[down]);j++) mp[i][j] = tolower(mp[i - 1][j]);
        }
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1;i <= n;i++)scanf("%s", mp[i] + 1);
    for (int i = 1;i <= n;i++)for (int j = 1;j <= m;j++) if (mp[i][j] == 'A')solve(i, j);


    for (int i = 1;i <= n;i++)printf("%s\n", mp[i] + 1);

}
posted @ 2021-03-02 21:56  —O0oO-  阅读(87)  评论(0编辑  收藏  举报