【题目描述】
给出一个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写回溯语句。