1. 程式人生 > >【CF1015E】Stars Drawing(貪心)

【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