letters 搜索与回溯

 

【题目描述】

给出一个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写回溯语句。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页