题目大意,给你一个n×m大小的字符矩阵,仅由‘.’和‘’组成,提问这个图可否划分为一些由‘’组成的十字形状,这些十字之间可以有重叠,如果可以完全覆盖输出每个十字中心坐标与边长度,不可以输出-1。
这是一道很有意思的题,在这场比赛中上一道题是这一道题的简化版本,数据范围仅有100,所以我采用了O(n^3)的做法,即枚举每个 * ,然后向四周扩展,显然,在这道题中1000的数据范围中这种做法会超时。
正确的做法类似与dp,首先开四个与字符数组相同大小的数组l,r,up,dn,然后进行两次扫描,这四个数组分别代表了从左边、右边、上边、下边开始数,数到当前位置的星号时已经有几个星号。然后再次扫描,枚举每一个星号,每一个星号上取l(i,j),
r(i,j),up(i,j),dn(i,j)中的最小值min(i,j),代表已当前位置为中心可能形成的最大十字,当min>1时代表当前十字合法。用一个vector记录下答案,扫一遍就可以找到所有十字。同时在开两个数组judgex与judgey,同样与字符数组一样大小,将十字一横中第一个格子judgex(i,j-min+1)加上一,将横中最后一个格子的下一个格子judgex(i,j+min)的值减一,同理将十字一竖中第一个格子judgey(i-min+1,j)加上一,将横中最后一个格子的下一个格子judgex(i+min,j)的值减一,同时分别对这两个数组求横向与纵向的前缀和,由此可以发现我们找的答案的十字中覆盖的值都大于0。
再进行一次扫描,如果图中当前位置为星号,且judgex与judgey的当前数值都为0,说明该星号不能被我们找到的答案中的十字中的任何一个覆盖,也就说明当前图不能完全被十字覆盖,不合法,输出-1,否则输出vector中记录下的答案。
#include <bits/stdc++.h>
using namespace std;
#define debug cout<<"???"<<endl
#define sync std::ios::sync_with_stdio(false)
#define ll long long
#define pb push_back
#define mp make_pair
#define MAXN 100005
#define INF 0x3f3f3f3f
#define frein freopen("input.txt", "r", stdin)
#define freout freopen("output.txt", "w", stdout)
char g[1005][1005];
int l[1005][1005],r[1005][1005],up[1005][1005],dn[1005][1005];
int jx[1005][1005],jy[1005][1005];
int n,m;
struct ans
{
int x,y;
int len;
};
vector <ans> p;
int main()
{
//sync;
//frein;
//freout;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",g[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='*'){
l[i][j]=l[i][j-1]+1;
up[i][j]=up[i-1][j]+1;
}
}
}
for(int i=n;i>=1;i--){
for(int j=m;j>=1;j--){
if(g[i][j]=='*'){
r[i][j]=r[i][j+1]+1;
dn[i][j]=dn[i+1][j]+1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='*'){
int len=INF;
len=min(min(l[i][j],r[i][j]),
min(up[i][j],dn[i][j]));
if(len>1){
ans temp;
temp.x=i;
temp.y=j;
temp.len=len-1;
p.pb(temp);
jx[i-len+1][j]++;
jx[i+len][j]--;
jy[i][j-len+1]++;
jy[i][j+len]--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
jx[i][j]+=jx[i-1][j];
jy[i][j]+=jy[i][j-1];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='*'&&jx[i][j]==0&&jy[i][j]==0){
printf("-1\n");
return 0;
}
}
}
int size=p.size();
printf("%d\n",size);
for(int i=0;i<size;i++){
printf("%d %d %d\n",p[i].x,p[i].y,p[i].len);
}
return 0;
}
暴搜代码
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define s_5(x,y,z,X,Y) scanf("%d%d%d%d%d",&x,&y,&z,&X,&Y)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x),scan_d(y)
#define S_3(x,y,z) scan_d(x),scan_d(y),scan_d(z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
typedef long long LL;
typedef pair <int, int> ii;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1};
const int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
const int maxn = 1e3 + 10;
const int maxx = 1e4 + 10;
const double EPS = 1e-8;
const double eps = 1e-8;
const int mod = 1e9 + 7;
template <class T> inline T min(T a, T b, T c) {return min(min(a, b), c);}
template <class T> inline T max(T a, T b, T c) {return max(max(a, b), c);}
template <class T> inline T min(T a, T b, T c, T d) {return min(min(a, b), min(c, d));}
template <class T> inline T max(T a, T b, T c, T d) {return max(max(a, b), max(c, d));}
template <class T> inline bool scan_d(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
inline bool scan_lf(double &num) {
char in;
double Dec = 0.1;
bool IsN = false, IsD = false;
in = getchar();
if (in == EOF) return false;
while (in != '-' && in != '.' && (in < '0' || in > '9')) in=getchar();
if (in == '-') {IsN = true; num = 0;}
else if (in == '.') {IsD = true; num = 0;}
else num = in - '0';
if (!IsD) {
while (in = getchar(), in >= '0' && in <= '9') {num *= 10; num += in - '0';}
}
if (in != '.') {
if (IsN) num = -num;
return true;
}
else{
while (in = getchar(), in >= '0' && in <= '9') {
num += Dec * (in - '0');
Dec *= 0.1;
}
}
if (IsN) num = num;
return true;
}
void Out(LL a) {if(a < 0) {putchar('-'); a = -a;}if(a >= 10) Out(a / 10); putchar(a % 10 + '0');}
void print(LL a) {Out(a), puts("");}
/**********************************************WHITE_YASHA**********************************************/
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
struct node {
int x, y, s;
node() {}
node(int _x, int _y, int _s) {
x = _x;
y = _y;
s = _s;
}
};
vector <node> v;
char g[maxn][maxn];
bool vis[maxn][maxn];
int n, m;
void solve(int x, int y) {
int ans = 1, f = 1, flag = 0;
W (f) {
FOr (0, 4, i) {
int xx = x + dx[i] * ans, yy = y + dy[i] * ans;
if (xx < 0 || yy < 0 || xx >= n || yy >= m || g[xx][yy] != '*') {
f = 0;
break;
}
}
if (f) {
vis[x + dx[0] * ans][y + dy[0] * ans] = vis[x + dx[1] * ans][y + dy[1] * ans] = vis[x + dx[2] * ans][y + dy[2] * ans] = vis[x + dx[3] * ans][y + dy[3] * ans] = vis[x][y] = true;
flag = 1;
ans++;
}
else break;
}
if (flag) v.pb({x + 1, y + 1, ans - 1});
}
int main() {
s_2(n, m);
FOr (0, n, i) scanf("%s", g[i]);
me(vis, false);
FOr (0, n, i) FOr (0, m, j) {
if (g[i][j] == '*') solve(i, j);
}
bool flag = true;
FOr (0, n, i) {
FOr (0, m, j) {
// printf("%d%s", vis[i][j], j == m - 1 ? "\n" : " ");
if (g[i][j] == '*' && !vis[i][j]) {
flag = false;
break;
}
}
if (!flag) break;
}
if (!flag || v.size() > n * m) printf("-1\n");
else {
printf("%d\n", (int)v.size());
foreach (it, v) printf("%d %d %d\n", it -> x, it -> y, it -> s);
}
}