letters 搜索与回溯

探讨在一个大写字母矩阵中,从左上角出发,如何通过上下左右移动,不重复走过相同字母,以收集尽可能多的不同字母。提供两段代码实现,详细解释了回溯算法的应用和坐标变化原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

【题目描述】

给出一个roe×colroe×col的大写字母矩阵,一开始的位置为左上角,你可以向上下左右四个方向移动,并且不能移向曾经经过的字母。问最多可以经过几个字母。

【输入】

第一行,输入字母矩阵行数RR和列数SS,1≤R,S≤201≤R,S≤20。

接着输出RR行SS列字母矩阵。

 

【输出】

最多能走过的不同字母的个数。

【输入样例】

3 6
HFDFFB
AJHGDH
DGAGEH

【输出样例】

6
#include<iostream>
#include<cstring>
using namespace std;

bool b[26];//26个字母 
char a[21][21];
int r, s;
int x[401];
int y[401];
int gx[4] = {1, -1, 0, 0},
	gy[4] = {0, 0, 1, -1};
int maxn = 0;

int dfs(int i)
{
//	if(maxn < i)
//		maxn = i;//考虑条件放在此处与放在下面的区别.(放在此处后输出的是maxn-1) 
	for(int j = 0; j < 4; j++)
	{
		x[i] = x[i-1] + gx[j];
		y[i] = y[i-1] + gy[j];
		if(!b[a[x[i]][y[i]]-65] && x[i] <= r && x[i] > 0 && y[i] < s && y[i] >= 0)
		{//横纵坐标与行列之间的关系需弄清。
			if(maxn < i)
				maxn = i;//放在此处,表示能走到i步 
			b[a[x[i]][y[i]]-65] = true;
			dfs(i+1);
			b[a[x[i]][y[i]]-65] = false;
		}
	}
}

int main()
{
	cin >> r >> s;
	for(int i = 1; i <= r; i++)
		cin >> a[i];//注意赋值是从a[i][0]开始。 
	b[a[1][0]-65] = true;
	x[1] = 1;
	y[0] = 1;
	dfs(2);
	cout << maxn;
}
#include<iostream>
using namespace std;

bool b[26];
int r, s;
char a[21][21];
int u[4] = {0, 0, 1, -1},
	v[4] = {1, -1, 0, 0};
int maxi;
int dfs(int x, int y, int i)
{
	if(i > maxi)
		maxi = i;
	int xx, yy;
	for(int j = 0; j < 4; j++)
	{
		xx = x + u[j];
		yy = y + v[j];
		if(!b[a[xx][yy]] && xx >= 0 && xx < r && yy < s && yy >= 0)
		{
			x += u[j];
			y += v[j];
			b[a[x][y]] = true;
			dfs(x, y, i+1);
			b[a[x][y]] = false;//这种写法需注意该条语句的位置,x在下面两条语句之后和在此处是有区别的。 
			x -= u[j];
			y -= v[j];
//			b[a[xx][yy]] = true; 
//			dfs(x, y, i+1);
//			b[a[xx][yy]] = false;
		}
	}
}

int main()
{
	cin >> r >> s;
	for(int i = 0; i < r; i++)
		for(int j = 0; j < s; j++)
		{
			cin >> a[i][j];
		}
	b[a[0][0]] = true;
	dfs(0, 0, 1);
	cout << maxi;
}

在回溯函数里不管是用a[i] = a[i-1] +...(dfs(int i))还是结用局部变量xx = x + ... 这种样的写法都是借用原先传入函数(比如dfs(int x, int y,int i)的x, y, i) 的参数在回溯后,其值在for循环内是不变的。因而借用这个特性,在递归调用语句后面可以不对xx写回溯语句。

### Python 回溯算法递归实现优化 #### 一、回溯算法的核心概念 回溯算法是一种基于度优先搜索(DFS)的递归技术,用于解决需要枚举多种可能性的问题。其核心在于通过递归的方式构建解决方案,并在不合适的情况下撤销之前的选择以返回上一层继续探索新的路径[^2]。 #### 二、基本框架结构 以下是典型的回溯算法模板: ```python def backtrack(path, choices): if 满足结束条件: 添加解到结果集中 返回 for choice in choices: 做出选择 (更新path) 进入下一层决策树 (backtrack(...)) 撤销选择 (恢复状态) ``` #### 三、具体案例分析——子集问题 以下是一个经典的子集生成问题及其优化版本: ##### 非优化版 该版本简单地利用递归来穷尽所有可能的组合。 ```python def subsets(nums): def backtrack(start, path): result.append(path[:]) for i in range(start, len(nums)): path.append(nums[i]) # 做出选择 backtrack(i + 1, path) # 进入下一层 path.pop() # 撤销选择 result = [] backtrack(0, []) return result ``` 此代码的时间复杂度为 \(O(2^n)\),其中 \(n\) 是输入数组长度[^3]。 ##### 优化思路 为了减少不必要的计算开销,在某些情况下可以通过提前判断剪枝来提升性能。例如对于重复元素的情况,可以先对 `nums` 排序再跳过相同值的分支。 #### 四、电话号码字母组合问题 这是一个常见的面试题目,涉及字符串映射关系以及如何有效组织递归逻辑。 ```python phone_map = { '2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz' } def letter_combinations(digits): if not digits: return [] def backtrack(index, combination): if index == len(digits): combinations.append(''.join(combination)) return letters = phone_map[digits[index]] for letter in letters: combination.append(letter) # 做出选择 backtrack(index + 1, combination) # 下探层次 combination.pop() # 撤销选择 combinations = [] backtrack(0, []) return combinations ``` 这段程序展示了如何将字符集合逐层扩展直至形成完整的单词串[^3]。 #### 五、总结建议 虽然标准形式已经足够清晰易懂,但在实际应用中还需考虑边界情况处理、内存占用等问题。适当引入缓存机制或者调整数据存储方式往往能带来显著改进效果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值