传送门E1
传送门E2
题目描述:
给你一张n*m的图,星星的概念是若一个点为‘*’,如果它的上下左右一格,两格.....n格都是‘*’,那么它就是一个星星。题目问你给你的这张图是否能够完全呗星星给覆盖,如果可以,则输出每个星星的中心点和延申的大小,否则输出-1。
E1的数据范围n,m<=100,而E2的数据范围n,m<=1000
题目分析:
事实上两个题的做法基本上是一样的,我们只需要对每个‘*’的位置暴力的扩展四个方向,找到每个‘*’可以拓展出的最大的星星,并将其存进答案即可。而题目问的是是否能够用星星完全覆盖整张图,我们可以在上述扩展的过程中,如果能够合法的扩展,就将合法位置打上标记,最后遍历整张图判断下是否有没有打上标记的‘*’即可,如果有就直接输出-1。
而这个题有一个坑点,就是倘若整张图都没有‘*’,答案应该是0而不是-1,这种情况特判一下即可。
E1,E2就改一改数据范围即可。
代码:
#include <bits/stdc++.h>
#define maxnE1 105
#define maxnE2 1005
using namespace std;
struct node{
int x,y;
int sz;
node(){}
node(int _x,int _y,int _sz){
x=_x,y=_y,sz=_sz;
}
}q[maxnE1];
vector<node>res;//存储答案
int n,m;
bool vis[maxnE1][maxnE1];
char str[maxnE1][maxnE1];
bool aha=0;//为0则证明没有出现过'*'
bool judge(int x,int y,int sz){//暴力扩展四个方向
int up=x-sz,down=x+sz,left=y-sz,right=y+sz;
if(up<0||down>n||left<0||right>m) return false;
if(str[up][y]=='*'&&str[down][y]=='*'&&str[x][left]=='*'&&str[x][right]=='*'){
vis[up][y]=1,vis[down][y]=1,vis[x][left]=1,vis[x][right]=1;
return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",str[i]);
}
for(int i=1;i<n-1;i++){
for(int j=1;j<m-1;j++){
int cnt=0;
if(str[i][j]=='*'){
aha=1;
bool flag=false;
while(judge(i,j,++cnt)){//不断向四周拓展
flag=true;
vis[i][j]=1;
}
if(flag) res.push_back(node(i,j,cnt-1));
}
}
}
if(res.size()==0&&aha){
puts("-1");
return 0;
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(str[i][j]=='*'&&!vis[i][j]){
puts("-1");
return 0;
}
}
}
cout<<res.size()<<endl;
int len=res.size();
for(int i=0;i<len;i++){
printf("%d %d %d
",res[i].x+1,res[i].y+1,res[i].sz);
}
return 0;
}