zoukankan      html  css  js  c++  java
  • 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
    ", mp[i] + 1);
    
    }
    
  • 相关阅读:
    使用isinstance()函数,判断输入的函数是否为已知的类型。raise() 引发异常。
    maya命令的运用。范例1。#举一反三
    maya中英文切换
    变量和maya命令 #getAttr #setAttr #xform #connectAttr #disconnectAttr
    变量和maya命令 #polySphere命令,创建、查询、编辑。
    PyCharm配置Maya开发环境
    希望与憧憬
    Java RandomAccessFile基本的用法
    Java 文件(File)类
    计算机编码问题
  • 原文地址:https://www.cnblogs.com/sduwh/p/14471565.html
Copyright © 2011-2022 走看看