对于存在不可能情况的构造题,我们的思路一般都是找到不存在的情况后,再进行构造。
这题首先能看出来的是,不能存在两个黑色之间有白色,因为这样一定会有一个黑色被吸引
在上面的情况下,如果存在某一列或某一行都是白的,但是没有与之对应的空白行列,那么也是非法的
满足了上面的情况下。答案就是连通块的数量,因为我们可以贪心的在每个黑色上面都放s,这样只需要一个n就能遍历一个连通块
如果所有行列都存在黑色且满足最上面的条件,那么白的摆放要求也能够满足。
不然如果存在某一行是白的,那么必定存在某一列也是白的,这点也可以想到。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+10; char s[1200][1200]; int st[1200][1200]; int n,m; void dfs(int x,int y){ if(s[x][y]=='.') return ; int dx[]={-1,0,1,0}; int dy[]={0,1,0,-1}; for(int i=0;i<4;i++){ int l=x+dx[i],r=y+dy[i]; if(l>=1&&l<=n&&r>=1&&r<=m){ if(s[l][r]=='#'&&!st[l][r]){ st[l][r]=1; dfs(l,r); } } } } int main(){ cin>>n>>m; int i,j; for(i=1;i<=n;i++){ scanf("%s",s[i]+1); } int cnt=0; int flag=0; int row=0; for(i=1;i<=n;i++){ cnt=0; for(j=1;j<=m;j++){ if(s[i][j]=='#'&&(s[i][j-1]!='#'||j==1)) cnt++; if(cnt>=2){ flag=1; break; } } if(!cnt) row=1; } int col=0; for(j=1;j<=m;j++){ cnt=0; for(i=1;i<=n;i++){ if(s[i][j]=='#'&&(s[i-1][j]!='#'||i==1)) cnt++; if(cnt>=2){ flag=1; break; } } if(!cnt) col=1; } if(flag){ cout<<"-1"<<endl; return 0; } else if(row^col){ cout<<"-1"<<endl; return 0; } cnt=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(s[i][j]=='.') continue; if(!st[i][j]){ dfs(i,j); cnt++; } } } cout<<cnt<<endl; }View Code