Stars Drawing
题面
题意
问是否可以利用长与宽相同的十字架把原图中※的覆盖,这里所说的宽与长与数学中的不同,所以你可以看题目开头与样例就知道是什么意思。
分析
这道题目数据范围只有3-100,所以很多方法都可以AC这道题。接下来我就讲一个暴力搜索的算法。
首先我们可以自己模拟这个过程,因为这道题目没有问最少需要多少个十字架,所以我们可以贪心一下,每次遇到一个※点的时候,我们就搜索四个方向的※的个数。然后取四个方向的※的个数最小值为这个十字架的长度。(贪心思想)
那么我如何搜索呢?
dfx dfy dfz dfd分别表示向上、向下、向左与向右的搜索方式。
int ans=0;
int dfx(int i,int j){
if(a[i-1][j]=='*') {ans++;dfx(i-1,j);}
else return ans;
}//这个只是部分模板,其他可以根据这个来理解写。注意ans的处理要注意,每次搜索的时候ans必须为0
还要就是怎样储存十字架,我们可以使用一个结构体
struct {
int x;
int y;
int z;
}c[10005];
只要搜索四个方向完后 ,四个方向的※的个数最小值大于0就表示有十字架,这时就可以直接储存在结构体数组里面。
每次搜索之后需要更新vis[][],vis表示目前已经储存在结构体的十字架覆盖的区域,然后程序最后直接扫一遍看有没有※的vis为0
AC代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,ans,b[102][102],vis[102][102];
char a[102][102];
struct {
int x;
int y;
int z;
}c[10005];
int dfx(int i,int j){
if(a[i-1][j]=='*') {ans++;dfx(i-1,j);}
else return ans;
}
int dfy(int i,int j){
if(a[i+1][j]=='*') {ans++;dfy(i+1,j);}
else return ans;
}
int dfz(int i,int j){
if(a[i][j-1]=='*') {ans++;dfz(i,j-1);}
else return ans;
}
int dfd(int i,int j){
if(a[i][j+1]=='*') {ans++;dfd(i,j+1);}
else return ans;
}
void update(int i,int j){
int num=b[i][j];
vis[i][j]=1;
for(int q=1;q<=num;q++){
vis[i-q][j]=1;
vis[i+q][j]=1;
vis[i][j-q]=1;
vis[i][j+q]=1;
}
return ;
}
int main(){
int cnt=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='*'){
int x=dfx(i,j);
ans=0;
int y=dfy(i,j);
ans=0;
int z=dfz(i,j);
ans=0;
int d=dfd(i,j);
ans=0;
b[i][j]=min(min(x,y),min(z,d));
if(b[i][j]) {
c[++cnt].x=i;
c[cnt].y=j;
c[cnt].z=b[i][j];
update(i,j);
}
}
}
}
/* for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cout<<vis[i][j]; putchar('\n'); }*/
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='*'&&vis[i][j]==0) {
printf("-1\n");return 0;
}
}
}
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++){
cout<<c[i].x<<' '<<c[i].y<<' '<<c[i].z<<endl;
}
return 0;
}