C/C++深度优先

文章介绍了使用深度优先搜索算法(DFS)解决两个问题:一是判断在给定棋盘上马是否能按字典序不重复地走完整个棋盘;二是检查一组长度不等的木棍是否能组成正方形。对于前者,DFS遍历所有可能的马的移动路径;对于后者,DFS尝试组合木棍以形成正方形的边。
摘要由CSDN通过智能技术生成

一、深度优先搜索

不撞南墙不回头
一般采用递归

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");
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值