Codeforces Round #639 (Div. 2)(D. Monopole Magnets 题解)(训练)
2020-7-4
D. Monopole Magnets
英语不好的人真的捉急!!!!!
题意:给你n*m的方格,其中有黑格子和白格子,你可以随意乱放S和N。如果N和S在同一行或同一列其中的N将会向S不断移动,在移动过程中N一定不可以出现在白色格子上,并且在所有operation完成后,每行每列必须要有一个S,问你最少需要几个N。
解读:1、由于N在移动过程中不能在白色格子上,因此每行每列中由黑色格子组成的线段必须不能在1条以上,否则不存在。
2、如果存在都为白的行,就必须要由全是白的列才会有可能存在,否则不存在。
3、如果存在,只需要判断有几个连通块即可。
同时看样例推理
代码
#include<bits/stdc++.h>
#define ll long long
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
char mp[1005][1005];
int vis[1005][1005];
int sum=0;
void dfs(int x,int y)
{
mp[x][y]='.';
if(mp[x+1][y]=='#'){
dfs(x+1,y);
}
if(mp[x-1][y]=='#'){
dfs(x-1,y);
}
if(mp[x][y+1]=='#'){
dfs(x,y+1);
}
if(mp[x][y-1]=='#'){
dfs(x,y-1);
}
return;
}
int main()
{
int n,m;
cin>>n>>m;
getchar();
mem(vis,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%c",&mp[i][j]);
}
getchar();
}
int k=1;
int p1,p2;
//行的线段
for(int i=1;i<=n;i++){
p1=0;
p2=0;
for(int j=1;j<=m;j++){
if(mp[i][j]=='#'&&p1==0){
p1=1;
}
if(p1&&mp[i][j]=='.'){
p2=1;
}
if(p1&&p2&&mp[i][j]=='#'){
k=0;
goto en;
}
}
}
//列的线段
for(int i=1;i<=m;i++){
p1=0;
p2=0;
for(int j=1;j<=n;j++){
if(mp[j][i]=='#'&&p1==0){
p1=1;
}
if(p1&&mp[j][i]=='.'){
p2=1;
}
if(p1&&p2&&mp[j][i]=='#'){
k=0;
goto en;
}
}
}
//空白行或列
int cc,rr;
cc=0;
rr=0;
for(int i=1;i<=n;i++){
p1=0;
for(int j=1;j<=m;j++){
if(mp[i][j]=='#'){
p1=1;
break;
}
}
if(p1==0){
cc++;
}
}
for(int i=1;i<=m;i++){
p1=0;
for(int j=1;j<=n;j++){
if(mp[j][i]=='#'){
p1=1;
break;
}
}
if(p1==0){
rr++;
}
}
//cout<<cc<<" "<<rr<<endl;
if((cc==0&&rr!=0)||(cc!=0&&rr==0)){
k=0;
}
en:;
if(k){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='#'){
dfs(i,j);
sum++;
}
}
}
cout<<sum;
}else{
cout<<-1<<endl;
}
return 0;
}
越自律,越自由