P1101 单词方阵

😊😊 😊😊
不求点赞,只求耐心看完,指出您的疑惑和写的不好的地方,谢谢您。本人会及时更正感谢。希望看完后能帮助您理解算法的本质
😊😊 😊😊

单词方阵

题目描述

给一 n × n n \times n n×n 的字母方阵,内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 8 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 * 代替,以突出显示单词。例如:

输入:
    8                     输出:
    qyizhong              *yizhong
    gydthkjy              gy******
    nwidghji              n*i*****
    orbzsfgz              o**z****
    hhgrhwth              h***h***
    zzzzzozo              z****o**
    iwdfrgng              i*****n*
    yyyygggg              y******g

输入格式

第一行输入一个数 n n n。( 7 ≤ n ≤ 100 7 \le n \le 100 7n100)。

第二行开始输入 n × n n \times n n×n 的字母矩阵。

输出格式

突出显示单词的 n × n n \times n n×n 矩阵。

样例 #1

样例输入 #1

7
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa

样例输出 #1

*******
*******
*******
*******
*******
*******
*******

样例 #2

样例输入 #2

8
qyizhong
gydthkjy
nwidghji
orbzsfgz
hhgrhwth
zzzzzozo
iwdfrgng
yyyygggg

样例输出 #2

*yizhong
gy******
n*i*****
o**z****
h***h***
z****o**
i*****n*
y******g

一、暴搜:😊

在这里插入图片描述

思路:

  1. 明确目标是所有的 yizhong,以字母: y y y 开头。启发我们以字符 y y y为突破口。
  2. 若以 y y y 为入口,则应该检测其某个方向上往后的8个字符是否符合目标字符。
  3. 题目要求把非目标字符串改成 “ ∗ ” “*” ,目标字符串保持不变。那么我们不仅要搜出目标字符串,还得进行标记,在最后输出的时候,利用标记进行特判!
  4. 那么为了检测到所有的字符 y y y,我们应该预处理出来 y y y的坐标。然后每个 y y y 都要依次搜索它的八个方向,且每个方向搜完后,回溯到起点 y y y 后才往下一个方向搜,回溯的时候也不能变换分支。否则会保留非目标字符串里的部分字符。
  5. 本题关键就在于:一次搜索,只能搜索一个方向,其每个方向上不能有分支,一旦出现分支,会导致信息错误!如下所示,若中途走向其他分支,则会错误地保留多的 h h h
    在这里插入图片描述

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 110;
int st[N][N];	//进行标记目标字符串上的每个字符为1,其余的没有标记的为0,即输出为 *;
char str[N][N];
int n;
string target = "yizhong";

//depth:深度,用于表示当前应该是目标字符串的第几个字符了 也是递归的出口. 
int dfs (int x, int y, int t1, int t2, int depth)
{
	if (depth == 6 && str[x][y] == target[depth])		//此时是递归的出口,说明在该方向上 
	{
		st[x][y] = 1;	//标记为1! 
		return 1;
	}
	//没有越界就去搜!
	if (str[x][y] == target[depth])
	{
		if (x+t1>=1  && x+t1<=n && y+t2>=1 && y+t2<=n)
		{
			if (dfs (x+t1, y+t2, t1, t2, depth+1))
			{
				st[x][y] = 1;
				return 1;
			}
		}
	}
	
	return 0;	//表示中断了没有搜到! 
}

int main()
{
	cin >> n;
	
	for (int i=1; i <= n; i ++)
	    for (int j=1; j <= n; j ++)
	        cin >> str[i][j];
		
	for (int i=1; i <= n; i ++)
	{
		for (int j=1; j <= n; j ++)
		{
			if (str[i][j] == 'y')	//入口 ==> 搜索! 
			{
				for (int t1=-1; t1 <= 1; t1 ++)
				{
					for (int t2=-1; t2 <= 1; t2 ++)
					{
						if (t1 == 0 && t2 == 0) continue;
						if (dfs (i+t1, j+t2, t1, t2, 1))
							st[i][j] = 1;
					}
				}
			}
		}
	}

	//打印方案:
	for (int i=1; i <= n; i ++)
	{
		for (int j=1; j <= n; j ++)
		{
			if (st[i][j]) cout << str[i][j];
			else cout << "*";
		}
		puts("");
	 } 
	
	return 0;
 } 

总结:初次总结,日后会逐步取其精华!

  1. 本题为在二维平面上搜索某个字符串,相比于之前的在二维平面上搜索时某个目标答案,通常是搜索出一套完整的方案后,再让你在终点判断该状态是否合法。
  2. 而本题在于一边搜索一边匹配答案是否合法。当然每个字符都有8个方向,若每个字符的8个方向都要去搜的话,则时间复杂度高,存在许多无效的搜索,不如固定起点,固定一个方向,每次只枚举起点的8个方向即可了!时间复杂度得到优化。
  3. 总结下本题的递归方式:
    (1)、递归的出口:分情况讨论,第一种情况:即当搜到目标字符串的最后一个字符时,即可进行答案的处理判断。第二种情况:即为不合法的情况下,则直接退出返回。
    (2)、递归的参数:(x,y)为当前位置的坐标。可以用来判断是否越界,(其实本题不用判断越界的,因为越界意味着并没有搜索到目标字符串,则等同处理)。(t1,t2)固定搜索方向用的。depth:递归的出口和判断当前搜索到的字符是否和目标字符的第 d e p t h depth depth 位相等!
    (3)、递归的计算:只要合法就往固定方向前进呗!

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值