一、深度优先搜索
不撞南墙不回头
一般采用递归
1)返回值设计
- 遍历 void
- 判断是否有路径 bool
2)参数设计 DFS(当前节点的信息,终点状态)
//去重isvisited
bool DFS(cur,end){
isvisited[cur]=true;
if(cur==end){
return true;
}
while(cur的邻居&&isvisited[cur邻居]==true){
if(DFS(cur的邻居,end)==true){
return true;
}
}
isvisted[cur]=false;
return false;
}
用法:判断是否有解
二、题目
1.A Knight’s Jouney
描述:
问在给的p*q的棋盘上,以象棋中马的行走方式,是否可以不重复的走完整个棋盘。若可以则输出任意一种行走方式,注意要按照字典序的方式输出。不可以就输出“impossible”。
#include<cstdio>
#include<string>
using namespace std;
int direction[8][2] = { {1,2},{-1,2},{2,1},{-2,1},{2,-1},{-2,-1},{1,-2},{-1,-2} };
bool isvisit[50][50];
bool DFS(int x, int y, int cur, int p, int q, string path) {
//把本节点加入到路径
path += (y + 'A');
path += (x + '1');
//已经走到终点
isvisit[x][y] = true;
if (cur == p * q) {
printf("%s\n\n", path.c_str());
return true;
}
//遍历邻居
for (int i = 0; i < 8; i++) {
if (x + direction[i][0] >= 0 && x + direction[i][0] < p &&
y + direction[i][1] >= 0 && y + direction[i][1] < q &&
isvisit[x + direction[i][0]][y + direction[i][1]] == false) {
if (DFS(x + direction[i][0], y + direction[i][1], cur + 1, p, q, path) == true) {
return true;
}
}
}
isvisit[x][y] = false;
path.substr(0, path.size() - 2);
return false;
}
int main() {
int n, p, q;
scanf_s("%d", &n);
for(int idx = 0; idx < n; idx++) {
scanf("%d%d", &p, &q);
printf("Scenario #%d:\n", idx + 1);
for (int i = 0; i < p; i++) {
for (int j = 0; j < q; j++) {
isvisit[i][j] = false;
}
}
string path;
if (DFS(0, 0, 1, p, q, path) == false) {
printf("impossible\n\n");
}
}
}
2.Square
描述:
给出一堆长度各异的木棍,这些木棍能否头尾相连形成一个正方形?
#include<cstdio>
int m;
int sticks[30];
bool isused[30];
//curside已经拼好的边长的个数
//curLength 正在拼的边长的个数
//position 木棍遍历的起点
bool DFS(int curSide,int curLength,int position,int side) {
if (curSide == 3) {
return true;
}
for (int i = position; i < m; i++) {
if (isused[i] == true || curLength + sticks[i] > side) {
continue;
}
isused[i] = true;
if (curLength + sticks[i] < side) {
if (DFS(curSide, curLength + sticks[i], i + 1, side) == true) {
return true;
}
}
else if (curLength == side) {
if (DFS(curSide + 1, 0, 0, side) == true) {
return true;
}
}
isused[i] = false;
}
return false;
}
int main() {
int n;
scanf_s("%d", &n);
for (int idx = 0; idx < m; idx++) {
scanf_s("%d", &m);
int total = 0;
for (int i = 0; i < m; i++) {
scanf_s("%d", &sticks[i]);
total += sticks[i];
isused[i] = false;
}
int side;//side是边长
if (total % 4 == 0) {
side = total / 4;
if (DFS(0, 0, 0, side) == true) {
printf("yes\n");
}
else {
printf("no\n");
}
}
else {
printf("no\n");
}
}
}