【CF1015E】Stars Drawing(貪心)
阿新 • • 發佈:2018-11-08
題意:給定一個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