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; }