目录
重要说明:本文提到#define的作用和using xxx = xxx的作用不会的请看:不会#define的作用戳我,不会using xxx=xxx的作用戳我
重要说明:本文提到#define的作用和using xxx = xxx的作用不会的请看:不会#define的作用戳我,不会using xxx=xxx的作用戳我
时间:1s 空间:256M
题目描述:
有一个的矩阵,矩阵中有两种颜色:黑('#'),白('.')
小信选了一个黑色位置 ,坐标为。当小信移动时,他可以往 4 个方向(上下左右)行进,但还有一个要求:假设当前小信从出发,他之后停下的位置坐标为,要求 与 的颜色不同。
具体图例:
最终小信会在白色位置,坐标为 停下。
请问有多少对可以从走到 。
输入格式:
第一行包含两个整数。
接下来包含一个 的矩阵。
输出格式:
输出一个整数表示答案。
样例1输入:
4 3
###
###
...
###
样例1输出:
6
样例2输入:
3 3
.#.
..#
#..
样例2输出:
10
约定与提示:
对于100%的数据,
对于样例1:其中一条路径为。
主要思路:
从题面上看,一看就知道是搜索,我们可以求一个和法的连通块(连通块说明(针对此题):就是设(x1,y1)能到(x2,y2)则路径上的点(包括起点和终点)就是一个连通块)注:(一个点在所有的连通块内只出现一次),接着根据乘法原理把连通块内的"#"的个数乘上连通块内的"."的个数就可以了。
注:十年OI一场空,不开xx见祖宗。
上代码(有注释):
//只有C++11,C++14,C++17,C++20才能使用using xxx=xxx
#include<bits/stdc++.h>
using namespace std;
//一堆几乎没用的东西。
#define ri register int
#define makedx4 int dx[]={0,-1,0,1}
#define makedy4 int dy[]={-1,0,1,0}
#define makedx8 int dx[]={0,-1,0,1,1,-1,1,-1}
#define makedy8 int dy[]={-1,0,1,0,1,-1,-1,1}
using ll=long long;
using ld = long double;
using d = double;
using f = float;
using pii=pair<int,int>;
using vi=vector<int>;
using si=set<int>;
using mii=map<int,int>;
using stint = stack<int>;
using queint = queue<int>;
using pqup = priority_queue<int,vector<int>,greater<int>>;
using pqdown = priority_queue<int,vector<int>,less<int>>;
using mci = map<char,int>;
using msi = map<string,int>;
using mic = map<int,char>;
using mis = map<int,string>;
//以下是主要部分
int n,m;//定义长和宽的变量
char a[410][410];//存字符矩阵
mci mp;//记录一个连通块中"."的数量和"#"的数量
int vis[410][410];//标记当前这个点有没有出现在连通块里过
//定义方向数组
makedx4;
makedy4;
void dfs(int x,int y)//dfs
{
mp[a[x][y]]++;//将当前的颜色数量+1
for(int i=0;i<4;i++)//枚举四个方向
{
int nowx=x+dx[i],nowy=y+dy[i];//记录备选新位置
if(nowx<1||nowx>n||nowy<1||nowy>m||vis[nowx][nowy]||a[x][y] == a[nowx][nowy])//如果不和法
{
continue;//跳出
}
vis[nowx][nowy] = 1;//否则标记当前点已经出现在连通块中过了
dfs(nowx,nowy);//dfs下一个
//注意,没有回溯
}
}
int main()
{
cin>>n>>m;//输入
for(int i=1;i<=n;i++)
{
cin>>a[i]+1;//读入矩阵
}
long long ans=0;//十年OI一场空,不开xx见祖宗。
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!vis[i][j])//如果没有出现在连通块中过,就当成一个新的连通块起点
{
mp['.'] = 0;//归零,因为是一个新的连通块
mp['#'] = 0;
vis[i][j] = 1;//起点要先标记
dfs(i,j);//dfs,启动!
ans+=1LL*mp['.']*mp['#'];//计算连通块的路径数量
}
}
}
cout<<ans;//输出
return 0;
}