【CF1015E】Stars Drawing(贪心)

题意:给定一个n×m大小的字符矩阵,仅由‘.’和‘*’组成,询问这个图可否划分为一些由‘*’组成的十字形状,这些十字之间可以有重叠,

如果存在方案则输出每个十字中心坐标与边长度,无解输出-1

n,m<=1e3

思路:感觉挺独特的一个思路,并没有能力完全自主推导,还是翻译一下题解……

因为任意一组方案都可以,所以可以把每一个能放星星的地方都扩展到最大

预处理每个点上下左右能扩展的长度,四个长度取min再-1就是半径,则将这个十字中所有的方格+1

对于每一行和每一列做一下差分后的前缀和,如果某个"*"的行列前缀和至少一个大于0则能放星星(并不理解)

若存在格子"*"的行列前缀和皆为0则无解

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 #define N 1100
 7 #define oo 10000000
 8 
 9 int f[N][N][5],sx[N][N],sy[N][N],x[N*N],y[N*N],z[N*N];
10 char a[N][N];
11  
12 int main()
13 {
14     int n,m;
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
17     for(int i=1;i<=n;i++)
18      for(int j=1;j<=m;j++)
19       if(a[i][j]=='*')
20      {
21          f[i][j][1]=f[i-1][j][1]+1;
22         f[i][j][3]=f[i][j-1][3]+1;
23      }
24     for(int i=n;i>=1;i--)
25      for(int j=m;j>=1;j--)
26       if(a[i][j]=='*')
27       {
28           f[i][j][2]=f[i+1][j][2]+1;
29         f[i][j][4]=f[i][j+1][4]+1;
30       }
31     int cnt=0; 
32     for(int i=1;i<=n;i++)
33      for(int j=1;j<=m;j++)
34       if(a[i][j]=='*')
35       {
36             int t=oo;
37             for(int k=1;k<=4;k++) t=min(t,f[i][j][k]);
38             if(t>1)
39             {
40                 x[++cnt]=i; y[cnt]=j; z[cnt]=t-1;
41                 sx[i-t+1][j]++; sx[i+t][j]--;
42                 sy[i][j-t+1]++; sy[i][j+t]--;
43             }
44       }
45     for(int i=1;i<=n;i++)
46      for(int j=1;j<=m;j++) 
47      {
48          sx[i][j]+=sx[i-1][j];
49          sy[i][j]+=sy[i][j-1];
50      }
51     int flag=0;
52     for(int i=1;i<=n;i++)
53      for(int j=1;j<=m;j++)
54       if(a[i][j]=='*'&&sx[i][j]==0&&sy[i][j]==0) flag=1;
55     if(flag) printf("-1\n");
56      else
57      {
58            printf("%d\n",cnt);
59           for(int i=1;i<=cnt;i++) printf("%d %d %d\n",x[i],y[i],z[i]);
60      }
61     return 0;
62 }
63     

猜你喜欢

转载自www.cnblogs.com/myx12345/p/9932309.html
今日推荐