思路:
由于不需要求最小覆盖,就可以在所有可覆盖的地方都覆盖上一个十字形。
对于每个点,预处理出它上下左右能延伸的最长距离,那么可以有它覆盖上的十字形的size为min{up,down,right,left}。
然后在处理出两个前缀和数组judgerow、judgecol,在每个可处理出的十字形的上下左右端点相应的进行加1减1。
当一个点为*且judgerow和judgecol均为0时,这个点不可被覆盖。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
int n,m;
char a[maxn+5][maxn+5];
int Up[maxn+5][maxn+5],Down[maxn+5][maxn+5],Left[maxn+5][maxn+5],Right[maxn+5][maxn+5];
int ans=0;
int X[maxn*maxn+5],Y[maxn*maxn+5],s[maxn*maxn+5];
int judgerow[maxn+5][maxn+5],judgecol[maxn+5][maxn+5];
void readin() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%s",a[i]+1);
}
}
void init() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(a[i][j]=='.') continue;
Up[i][j]=Up[i-1][j]+1;
Right[i][j]=Right[i][j-1]+1;
}
}
for(int i=n;i>=1;i--) {
for(int j=m;j>=1;j--) {
if(a[i][j]=='.') continue;
Down[i][j]=Down[i+1][j]+1;
Left[i][j]=Left[i][j+1]+1;
}
}
}
bool judge() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(a[i][j]=='.') continue;
int Min=min(min(Up[i][j],Down[i][j]),min(Left[i][j],Right[i][j]))-1;
if(Min<=0) continue;
judgecol[i][j-Min]++,judgecol[i][j+Min+1]--;
judgerow[i-Min][j]++,judgerow[i+Min+1][j]--;
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
judgecol[i][j]+=judgecol[i][j-1];
judgerow[i][j]+=judgerow[i-1][j];
if(a[i][j]=='*'&&!judgecol[i][j]&&!judgerow[i][j]) return false;
}
}
return true;
}
int count() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(a[i][j]=='.') continue;
int Min=min(min(Up[i][j],Down[i][j]),min(Left[i][j],Right[i][j]))-1;
if(Min<=0) continue;
ans++;
X[ans]=i,Y[ans]=j,s[ans]=Min;
}
}
}
void print() {
printf("%d\n",ans);
for(int i=1;i<=ans;i++) {
printf("%d %d %d\n",X[i],Y[i],s[i]);
}
}
int main() {
readin();
init();
if(!judge()) {
printf("-1");
return 0;
}
count();
print();
return 0;
}