版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30358129/article/details/81583082
题意:
给出一个n*m的图,四方向的最大长度相同为一个星星,问能否找到不大于n*m颗星星,使得图中的所有都被星星覆盖。
思路:
首先o(n^2)算出所有*能扩展的最大规格,4个方向dp求最小值
然后o(n^2) 用差分前缀和的方法进行填充
值得一提的是,这题的标程tle了,因为使用的cin/cout输入输出
#include <bits/stdc++.h>
#define Pii pair<int,int>
using namespace std;
const int N = 1100;
int u[N][N],d[N][N],l[N][N],r[N][N],s1[N][N],s2[N][N];
struct node{
int x,y,z;
node(int a,int b,int c){
x = a;
y = b;
z = c;
}
};
int main(){
int n,m,i,j;
bool s[N][N];
cin>>n>>m;
for(i = 1;i <= n;i ++)
for(j = 1;j <= m;j ++){
char c;
cin>>c;
if(c=='*') s[i][j] = 1;
else s[i][j] = 0;
}
for(i = 1;i <= n;i ++)
for(j = 1;j <= m;j ++)
if(s[i][j]) {
u[i][j] = u[i-1][j]+1;
l[i][j] = l[i][j-1]+1;
}
for(i = n;i >= 1;i --)
for(j = m;j >= 1;j --)
if(s[i][j]) {
d[i][j] = d[i+1][j]+1;
r[i][j] = r[i][j+1]+1;
}
vector<node>ans;
for(i = 1;i <= n;i ++)
for(j = 1;j <= m;j ++)
if(s[i][j]) {
int x = min(u[i][j],d[i][j]);
x = min(x,l[i][j]);
x = min(x,r[i][j]);
if(x==1) continue;
node p(i,j,x);
ans.push_back(p);
s2[i+x][j] += -1;
s2[i-x+1][j] += 1;
s1[i][j+x] += -1;
s1[i][j-x+1] += 1;
}
for(i = 1;i <= n;i ++)
for(j = 1;j <= m;j ++)
s1[i][j] += s1[i][j-1];
for(j = 1;j <= m;j ++)
for(i = 1;i <= n;i ++)
s2[i][j] += s2[i-1][j];
for(i = 1;i <= n;i ++)
for(j = 1;j <= m;j ++){
if(s[i][j]&&s1[i][j]==0&&s2[i][j]==0){
cout<<"-1";
return 0;
}
}
cout<<ans.size()<<endl;
for(auto v:ans){
printf("%d %d %d\n",v.x,v.y,v.z-1);
}
return 0;
}