题目链接:https://www.acwing.com/problem/content/5168/
题目:
给定一个 R×C 的大写字母矩阵。
请你在其中寻找目标单词 W。
已知,目标单词 W 由若干个不同的大写字母构成。
目标单词可以遵循以下两种规则,出现在矩阵的水平、垂直或斜 45度线段中:
- 单词出现在一条线段上。
- 单词出现在两条相互垂直且存在公共端点的线段上。也就是说,单词首先出现在某线段上,直到某个字母后,转向 90 度,其余部分出现在另一条线段上。
具体可以参照图例。
请你计算,目标单词在给定矩阵中一共出现了多少次。
输入格式
第一行包含一个由若干个不同的大写字母构成的字符串,表示单词 W。
第二行包含整数 R。
第三行包含整数 C。
接下来 R行,每行包含 C 个大写字母,表示给定字母矩阵。
输出格式
一个整数,表示目标单词在给定矩阵中的出现次数。
数据范围
2≤|W|≤6
1≤R,C≤100
输入样例1:
MENU
5
7
F T R U B L K
P M N A X C U
A E R C N E O
M N E U A R M
M U N E M N S
输出样例1:
3
输入样例2:
NATURE
6
9
N A T S F E G Q N
S A I B M R H F A
C F T J C U C L T
K B H U P T A N U
D P R R R J D I R
I E E K M E G B E
输出样例2:
4
思路:dfs深搜,分两部分搜索,与以往不同的是,该题只能转一次弯,需要加参数判断,比较有意思
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n"
int n,m,k,sum,l;
int d1[4][2]={0,1,0,-1,1,0,-1,0};
int d2[4][2]={-1,-1,1,1,1,-1,-1,1};
char x[105][105];
string st;
void dfs1(int x1,int y1,int t,int ans)
{
if(k==l&&ans<2)
{
sum++;
return ;
}
for(int i=0;i<4;i++)
{
int xx=x1+d1[i][0];
int yy=y1+d1[i][1];
if(xx>n||yy>m||xx<1||yy<1)
continue;
if(x[xx][yy]==st[k])
{
k++;
if(t!=i&&k!=2)
dfs1(xx,yy,i,ans+1);
else
dfs1(xx,yy,i,ans);
k--;
}
}
}
void dfs2(int x2,int y2,int t,int ans)
{
if(k==l&&ans<2)
{
sum++;
return ;
}
for(int i=0;i<4;i++)
{
int xx=x2+d2[i][0];
int yy=y2+d2[i][1];
if(xx>n||yy>m||xx<1||yy<1)
continue;
if(x[xx][yy]==st[k])
{
k++;
if(t!=i&&k!=2)
dfs2(xx,yy,i,ans+1);
else
dfs2(xx,yy,i,ans);
k--;
}
}
}
void solve()
{
cin>>st;
l=st.size();
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>x[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(x[i][j]==st[0])
{
k=1;
dfs1(i,j,0,0);
k=1;
dfs2(i,j,0,0);
}
}
}
cout<<sum<<endl;
return ;
}
signed main()
{
IOS
int t=1;
//cin>>t;
while(t--)
solve();
return 0;
}