CF 。E2. Stars Drawing (Hard Edition) (DP)

Description:

定义一个星星由 '*' 组成,形状为一个对称的“十”字型,大小为星星 1/2 的横长(或纵长)减一(如题目中的图)。给出一个 n*m 的图,判断是不是每一个 '*' 都能属于某个星星,如果能则输出所有星星的位置及大小(各个星星间可以出现重叠甚至重合),否则输出-1.

 

Solution:

f[i][j][k] 代表在当前位置 (i, j) 在 k 方向有多少个连续的星号 '*'(1代表上,2代表下,3代表左,4代表右)。

枚举每一个星号(i, j),每一个星号上取 f[i][j][k](1 <= k <= 4) 中的最小值min,代表已当前位置为中心可形成的最大星星,当min > 1时代表当前星星合法。用vector记录下答案,扫一遍就可以找到所有星星。

同时用两个数组 presum_x 与 presum_y 表示当前星星的覆盖值,如果当前星星的位置为(i, j),大小为 d,那么将当前星星横向的左端点加一(presum_x[i-d+1][j]++),右端点加一的位置上减一(presum[i+d][j]--);同理,星星纵向的上端点加一(presum_y[i][j-d+1]++),下端点加一的位置上减一(presum_y[i][j+d]--)。

然后分别对这两个数组求横向和纵向的和,可以得出,所有找到的答案中的星星的覆盖值都大于0(妙啊)。所以,再进行一次扫描,如果当前位置为星号,且纵向和横向的覆盖值都为0,说明当前图中的所有星号不能被完全覆盖,输出-1,否则输出vector中记录下的答案。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const int Mod = 1e9 + 7;
const int MaxN = 1e5 + 5;

struct node {
    int x, y, d;
};

char s[1005][1005];
int f[1005][1005][5];
int presum_x[1005][1005], presum_y[1005][1005];
int n, m;

void init() {
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%s", s[i] + 1);
        for(int j = 1; j <= m; j++) {
            if(s[i][j] == '*') {
                f[i][j][1] = f[i-1][j][1] + 1;
                f[i][j][3] = f[i][j-1][3] + 1;
            }
            //else f[i][j][1] = f[i][j][3] = 0;
        }
    }
    for(int i = n; i >= 1; i--) {
        for(int j = m; j >= 1; j--) {
            if(s[i][j] == '*') {
                f[i][j][2] = f[i+1][j][2] + 1;
                f[i][j][4] = f[i][j+1][4] + 1;
            }
            // else f[i][j][4] = f[i][j][2] = 0;
        }
    }
}

vector <node> res;

int main()
{
    //Fio;

    init();
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(s[i][j] == '*') {
                int d = min(min(f[i][j][1], f[i][j][2]), min(f[i][j][3], f[i][j][4]));
                if(d > 1) {
                    res.push_back((node){i, j, d-1});
                    presum_x[i-d+1][j]++; presum_x[i+d][j]--;
                    presum_y[i][j-d+1]++; presum_y[i][j+d]--;
                }
            }
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            presum_x[i][j] += presum_x[i-1][j];
            presum_y[i][j] += presum_y[i][j-1];
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(s[i][j] == '*' && presum_x[i][j] == 0 && presum_y[i][j] == 0) {
                printf("-1
");
                return 0;
            }
        }
    }
    printf("%d
", res.size());
    for(int i = 0; i < res.size(); i++) printf("%d %d %d
", res[i].x, res[i].y, res[i].d);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuaihui520/p/9436734.html