遍历算法

遍历算法

1.DFS(Depth-First Search)

从某状态出发,不断转移状态直到无法转移,退回前一格的状态,不断反复直到结束。 DFS可用栈,但用递归实现较为简单。

1.部分和问题

给定整数a1,a2,……an,判断是否可以从中显出若干数,是他们的和恰好为k。
示例:
n=4
k=15
a={3,5,6,7}

设递归函数 (i,sum)

表示搜索到第i个数时,搜索前0,1,2……i-1个数的和sum,当搜索到某一个数时有挑选和不挑选两种选择。
注:程序的下标从0开始。
时间复杂度:O(2^n)
在这里插入图片描述

#include"stdio.h"
#include"stdlib.h"
#define MAX 100
int a[MAX];
int n, k;
bool dfs(int i,int sum) {
	//当搜索完所有数时结束
	if (i == n) return sum == k;
	//分支两种情况,挑选和不挑选
	if (dfs(i + 1, sum + a[i])) return true;
	if (dfs(i + 1, sum)) return true;
	else return false;
}
int main() {
	scanf_s("%d%d", &n,&k);
	for (int i = 0; i < n; i++)
		scanf_s("%d", &a[i]);
	if (dfs(0, 0)) puts("Yes");
	else puts("No");
	system("pause");
}

2. Lake Counting

有一个大仙为N*M的院子,雨后激起了水。八联通的积水被认为是连在一起的。请求出院子里总共有多少水洼?(“w”表示积水,“.”表示没有积水)

示例:N=6,M=6
ww . . . .
. w . . . .
. . .www
w . . . . .
www. . .
www. . .

建立数组field[6][6]来存储上述地图

以field[0][0]为例("-"表示在规定区域之外)
在这里插入图片描述

步骤一: 将所选区域标记为“.”,从而不再遍历此点
步骤二: 对field[0][0]的八个临近的区域搜索: 设置水平方向的偏移量dx,竖直方向上的偏移量dy for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++)
二重循环遍历8个区域
步骤三: 判断是否继续递归: 当所选区域在规定区域内,且是w(积水)时继续

当一次DFS后与初始连接的w全被替换成了“.”,搜索所有区域,调用DFS的次数就是积水的个数了
时间复杂度:O(8NM)

#include"stdio.h"
#include"stdlib.h"
#define MAX 100
char field[MAX][MAX];
int M, N;w
int nums = 0;
void dfs(int x, int y) {
	field[x][y] = '.';
	for (int dx = -1; dx <= 1; dx++) {
		for (int dy = -1; dy <= 1; dy++) {
			int nx = dx + x;
			int ny = dy + y;
			if (nx >= 0 && nx < N&& ny >= 0 && ny < M && field[nx][ny] == 'w') dfs(nx, ny);
		}
	}
}
void solve() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (field[i][j] == 'w') {
				dfs(i, j);
				nums++;
			}
		}
	}
}
int main() {
	scanf_s("%d%d", &M, &N);
	for (int i = 0; i < N; i++)
		scanf_s("%s", field[i], MAX);
	solve();
	printf("%d\n", nums);
	system("pause");
}

2.BFS(Breadth-First Search)

与深度优先遍历不同的时搜索顺序,宽度优先遍历总是先搜索距离与初始状态近的状态,因此容易用来解决最短路径,最少操作之类的问题。

BFS用队列解决问题,在C++的标准库中预置有队列

#include"queue"
using namespace std;
queue<int> que;//声明int存储类型的队列
que.push();//进队
que.front();//获得队首元素
que.pop();//队首元素出队

BFS模板:

void bfs() {
	que.push(start);
	…… ……
	while (que.size()) {
	    que.front();   
		que.pop();
		…… ……
				if () {
					que.push(next);
					…… ……
				}
	}
}

Maze问题

给定大小为N*M的迷宫,求最短路径(’#’, ‘.’ , ‘S’, 'D’分别代表墙壁,通道,起点和终点)
示例:N=6,M=6
#S. . . .
##. . ##
##. . ##
##. ###
#.D###
##. ###
在这里插入图片描述

#include"stdio.h"
#include"stdlib.h"
#include"queue"
using namespace std;
#define INF 10000
#define MAX 100

typedef struct {
	int x, y;
}Ptr;

char maze[MAX][MAX];
int sx, sy;
int dx, dy;
int M, N;
int d[MAX][MAX];
int a[4] = { -1,0,1,0 }, b[4] = { 0,1,0,-1 };
queue<Ptr> que;

void Initial() {
	scanf_s("%d%d", &M, &N);
	scanf_s("%d%d", &sx, &sy);
	scanf_s("%d%d", &dx, &dy);
	for (int i = 0; i < M; i++)
		scanf_s("%s", maze[i], MAX);
	for (int i = 0; i < M; i++)
		for (int j = 0; j < N; j++)
			//用于标记某点是否被访过
			d[i][j] = INF;
}
void bfs() {
	Ptr start;
	start.x = sx; start.y = sy;
	d[sx][sy] = 0;
	que.push(start);
	while (que.size()) {
	    Ptr p = que.front();   
		que.pop();
		if (p.x == dx&&p.y == dy)  break;
		for (int i=0;i<4;i++) {
				Ptr next;
				int nx = p.x + a[i];
				int ny = p.y + b[i];
				next.x = nx; 
				next.y = ny;
				if (nx >= 0 && nx < N&&ny >= 0 && ny < M&&d[nx][ny] == INF&&maze[nx][ny] != '#') {
					que.push(next);
					d[next.x][next.y] = d[p.x][p.y] + 1;
				}
			}
	}
}
int main(){
	Initial();
	bfs();
	printf("%d", d[dx][dy]);
	system("pause");
}

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值