题目链接:
https://codeforces.ml/problemset/problem/1344/B
解题思路:
啊啊啊啊啊!!!打CF时想的正解被自己傻X的否定掉了…
首先,同一行或者同一列,只能有连续的一段,如果有多段,则必然不行
因为南极是每一行以及每一列都要有,假设a和b为同一行上不相邻的两个#,那么该行的南极无论放哪都可能会使北极到白格上
如果有一行全为空白格,全部列都至少有一个#,那么该行的南极无论放哪,都不符合题意(列反过来即可)
最后,答案即为连通块的个数,因为北极只能在本身所在的连通块移动,所以为了最少,肯定每个连通块只有一个啦!!!
AC代码:
#include<bits/stdc++.h>
using namespace std;
char Map[1010][1010];
int vis[1010][1010];//vis[i][j]代表这是哪个连通块(#相连的)
int row[1010],column[1010];
int n,m,flag=1;
void dfs(int x,int y,int cnt) {
if(x<1||x>n||y<1||y>m||vis[x][y]||Map[x][y]=='.') return;
vis[x][y]=cnt;
dfs(x+1,y,cnt);
dfs(x-1,y,cnt);
dfs(x,y+1,cnt);
dfs(x,y-1,cnt);
return;
}
int main() {
int cnt=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%s",Map[i]+1);
//先计算出每一行以及每一列有多少段连续的
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(Map[i][j]=='#'&&Map[i][j-1]!='#')
row[i]++;
for(int j=1; j<=m; j++)
for(int i=1; i<=n; i++)
if(Map[i][j]=='#'&&Map[i-1][j]!='#')
column[j]++;
int num1=0,num2=0;
for(int i=1; i<=n; i++)
if(row[i]>1) flag=0;//如果出现一行或者一列内有多段连续的那么则不成立
else if(!row[i]) num1++;//计算有多少行空白的
for(int i=1; i<=m; i++)
if(column[i]>1) flag=0;
else if(!column[i]) num2++;//计算有多少列空白的
if(!flag||num1>0&&num2==0||num1==0&&num2>0) {
//ps:注意是有一行为空白的,不是只有一行
printf("-1\n");
return 0;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(Map[i][j]=='#'&&vis[i][j]==0)
dfs(i,j,++cnt);
printf("%d\n",cnt);
return 0;
}