在经过几天对bfs和dfs的学习后,自认为把握十足的我开始了刷题。然而,现实却给了我当头一棒。我发现我做了几个题中,只有那么几个是对的,有许多并没有对。除此之外,我发现我对bfs还是及其的不熟悉,只会用dfs进行求解。(可能是dfs较bfs的代码思维较为简单些吧)所以,我就对我写对的题进行一下总结。
题目描述
给定一个 N×M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标,FX,FY 代表终点坐标。
接下来 T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
输入输出样例
输入 #1复制
2 2 1 1 1 2 2 1 2
输出 #1复制
1
说明/提示
对于 100%100% 的数据,1≤N,M≤5,1≤T≤10,1≤SX,FX≤n,1≤SY,FY≤m。
代码如下:
#include<cstdio>
using namespace std;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, -1, 0, 1};//定义方向数组
int n = 0, p, q, t, N, M;
int v[100][100] = {0};//定义访问数组,并设为全未访问
struct point {//定义结构体,表示障碍坐标
int x;
int y;
};
void dfs(int x, int y, struct point s[], int t) {
if (x == p && y == q) {//如果一条路可抵达终点,则n加1,并回溯路径
n++;
return;
}
for (int i = 0; i < 4; i++) {
int tx = x + dx[i];
int ty = y + dy[i];//点的移动
if (tx >= 1 && tx <= N && ty >= 1 && ty <= M && v[tx][ty] == 0) {//判断点是否出界,是否被访问
int flag=1;
for (int j = 0; j < t; j++) {//通过循环遍历各障碍点,判断运动点是否为障碍点
if (tx == s[j].x && ty == s[j].y) {//当确定点为障碍点时,循环可以停止,且将flag赋值为0,排除障碍点进行深搜的可能
flag=0;
break;
}
}
if (flag==1) {//对非障碍点进行深搜
v[tx][ty] = 1;
dfs(tx, ty, s, t);
v[tx][ty] = 0;
}
}
}
return;
}
int main() {
scanf("%d %d %d", &N, &M, &t);
struct point s[t];
int startx, starty;
scanf("%d %d %d %d", &startx, &starty, &p, &q);//输入起点、终点
for (int i = 0; i < t; i++) {//输入障碍坐标
scanf("%d %d", &s[i].x, &s[i].y);
}
v[startx][starty] = 1;//设置起点为访问状态
dfs(startx, starty, s, t);
printf("%d", n);//输出路径条数
return 0;
}
该题的思路主要就是先定义一个结构体表示障碍坐标,然后再编写深搜函数。在每次递归前,判断点是不是障碍点,然后在一直深搜,直至终点则路径多一条,最后在进行输出。
A - Rook
你可能知道,国际象棋是一种在一个排列成8x8网格的棋盘上进行的游戏。这个棋盘的列用从a到h的字母标记,行用从1到8的数字标记。每个方格由它所属的行和列来描述。
车是国际象棋中的一个棋子。在它的回合中,它可以水平或垂直地移动任意非零数量的方格。你的任务是找出车在空棋盘上所有可能的移动方式。
输入
输入的第一行包含一个整数t(1≤t≤64)— 测试用例的数量。接下来是每个测试用例的描述。
每个测试用例包含一个由两个字符组成的字符串,描述了车所在的方格。第一个字符是从a到h的字母,表示列的标记,第二个字符是从1到8的数字,表示行的标记。
相同的位置可能出现在多个测试用例中。
输出
对于每个测试用例,以与输入相同的格式输出车可以移动到的所有方格的描述。
你可以以任何顺序输出每个测试用例中的方格。
示例 1
Inputcopy | Outputcopy |
---|---|
1 d5 | d1 d2 b5 g5 h5 d3 e5 f5 d8 a5 d6 d7 c5 d4 |
Sponsor
代码如下:
#include<bits/stdc++.h>
using namespace std;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, -1, 0, 1};//定义方向数组
void dfs1(int x, int y, int i) {
if (x < 'a' || x > 'h' || y < '1' || y > '8') {//判断坐标点是否出界
return;
}
printf("%c%c ", x, y);//输出结果
int tx = x + dx[i];
int ty = y + dy[i];
dfs1(tx, ty, i);//从运动过后的开始进行搜索
return;
}
void dfs(char x, char y) {
if (x < 'a' || x > 'h' || y < '1' || y > '8') {//判断坐标点是否出界
return;
}
for (int i = 0; i < 4; i++) {
int tx = x + dx[i];
int ty = y + dy[i];
dfs1(tx, ty, i);
}
return;
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0; i < t; i++) {
char x, y;
getchar();//吸收回车
scanf("%c%c", &x, &y);
dfs(x, y);//从给出的点开始深搜
}
return 0;
}
这个题目的难点就是这个象棋只会沿直线走,所以就要求你处理好它的运动方向。所以,我们就可以先写一个函数,确定其运动方向。再写一个记录方向的深搜函数,不断沿同一方向进行深搜,最后输出结果即可。