分析
显然搜索题,但是范围是两百,不能每个点都递归,参照之前的题,会出现一些能递归的关键点。
我们先对于每个点上下左右走到头,求出每个点对应的下一个关键点,然后从起点开始递归,对于每个点记录有没有“走过”,和有没有递归过,然后到达每个点都去找关键点就行。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,cnt,ans;
int a[210][210],key[210][210][5],p[210][210],v[210][210];
int dx[5]={0,-1,1,0,0};
int dy[5]={0,0,0,-1,1};
void dfs(int x,int y)
{
for(int i=1;i<=4;i++)
{
if(key[x][y][i]==a[x][y]) continue;//这个方向走不了
int xx=x+dx[i];
int yy=y+dy[i];
while(a[xx][yy]!=key[x][y][i]) //找关键点
{
p[xx][yy]=1;
xx+=dx[i];
yy+=dy[i];
}
p[xx][yy]=1;
if(!v[xx][yy])
{
v[xx][yy]=1;
// cout<<xx<<' '<<yy<<endl;
dfs(xx,yy);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char c;
cin>>c;
if(c=='.') a[i][j]=++cnt;
else a[i][j]=-1;
}
}
for(int i=2;i<=n-1;i++)
{
for(int j=2;j<=m-1;j++)
{
if(a[i][j]==-1) continue;
/*尝试上下左右*/
for(int k=1;i-k>=1;k++)
{
if(a[i-k][j]==-1)
{
key[i][j][1]=a[i-k+1][j];break;
}
}
for(int k=1;i+k<=n;k++)
{
if(a[i+k][j]==-1)
{
key[i][j][2]=a[i+k-1][j];break;
}
}
for(int k=1;j-k>=1;k++)
{
if(a[i][j-k]==-1)
{
key[i][j][3]=a[i][j-k+1];break;
}
}
for(int k=1;j+k<=m;k++)
{
if(a[i][j+k]==-1)
{
key[i][j][4]=a[i][j+k-1];break;
}
}
}
}
v[2][2]=1;//!!
p[2][2]=1;//!!
dfs(2,2);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
// if(a[i][j]==-1)
// {
// cout<<'#';
// continue;
// }
if(p[i][j])
{
// cout<<'x';
ans++;
}
// else cout<<'.';
}
// cout<<endl;
}
cout<<ans;
return 0;
}