Fork me on GitHub

数据结构与算法-搜索(二)-递归


数据结构与算法-搜索(二)-递归

汉诺塔问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>

void move(int n,char a,char b,char c)
{
if(n==1)
printf("\t%c->%c\n",a,c); //当n只有1个的时候直接从a移动到c
else
{
move(n-1,a,c,b); //把a的n-1个盘子通过c移动到b
printf("\t%c->%c\n",a,c); //把a的最后1个盘(最大的盘)移动到c
move(n-1,b,a,c); //吧b上面的n-1个盘通过a移动到c
}
}

main()
{
int n;
printf("请输入要移动的块数:");
scanf("%d",&n);
move(n,'a','b','c');
}

汉诺塔三

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <cstring>

long long F(int num){
if(num == 1) return 2;
else return 3*F(num-1)+2;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
printf("%lld\n",F(n));
}
return 0;
}

递归的应用(一)-回溯法枚举

题目描述:

A ring is compose of n circles as shown in diagram.Put natural nuber 1,2,…,n into each circle separately,and the sum of numbers in two adjacent circles should be a prime.

Note: the number of first circle should always be 1.

输入:

n (1 < n < 17)

输出:

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirement.

Print solutions in lexicographical order.

You are to write a program that completes above process.

Print a blank line after each case

样例输入:

1
2
6
8

样例输出:

1
2
3
4
5
6
7
8
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4
Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <cstring>

using namespace std;

int ans[22]; // 保存环中每一个被放入的数
bool hash[22]; // 标记之前已经被放入环中的数
int n;
int prime[] = {2,3,5,7,11,13,17,19,23,29,31,37,41};
// 素数,若需判断一个数是否为素数则在其中查找,因为输入不大于16,固两数和构成的素数必在该数组内
bool judge(int x){
for(int i = 0 ; i < 13 ; i++){
if(prime[i] == x) return true;
}
return false;
}

void check(){
if(judge(ans[n]+ans[1]) == false) return;
// 判断最后一个数与第一个数的和是否为素数,若不是直接返回
for(int i = 1 ; i <= n ; i++){
if(i != 1) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
void DFS(int num){ // 递归枚举,num为当前已经放入环中的数字
if(num > 1)
if(judge(ans[num]+ans[num-1]) == false) return;
// 判断最后两个数字的和是否为素数,若不是则返回继续枚举第num个数
if(num == n){ // 若已经放入了n个数
check(); // 检查输出
return;
}
for(int i = 2 ; i <= n ; i++){ // 放入一个数
if(hash[i] == false){ // 若i还没有被放入环中
hash[i] = true;
ans[num+1] = i; // 将这个数字放入ans数组中
DFS(num+1); // 继续尝试放入下一个数
hash[i] = false; // 当回溯枚举该位数字时,将i重新标记为未使用
}
}
}
int main(){
int cas = 0; // 记录Case数
while(scanf("%d",&n)!=EOF){
cas++;
for(int i = 0 ; i < 22 ; i++) hash[i] = false; // 初始化标记所有数字为未被使用
ans[1] = 1; // 第一个数字恒定为1
printf("Case %d:\n",cas);
hash[1] = true; // 标记1被使用
DFS(1); // 继续尝试放入下一个数字
printf("\n");
}
}

运行结果:

递归的应用(一)-图的遍历

题目描述:

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposits. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.

输入:

The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <=m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each( not counting the end-of-line characters). Each character corresponds to one plot, and is either ‘*’, representing the absence of oil, or ‘@’, representing an oil pocket.

输出:

For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent hozizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.

样例输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

样例输出:

1
2
3
4
0
1
2
2

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <cstdio>

using namespace std;

char maze[101][101]; // 保存地图信息
bool mark[101][101]; // 为图上每一个点设立一个状态
int n,m;
int go[][2] = {
1,0,
-1,0,
0,1,
0,-1,
1,1,
1,-1,
-1,-1,
-1,1
};

void DFS(int x,int y){
for(int i = 0 ; i < 8 ; i++){
int nx = x+go[i][0];
int ny = y+go[i][1];
if(nx < 1 || nx > n || ny < 1 || ny > m) continue; // 若该坐标在地图外
if(maze[nx][ny] == '*') continue; // 若该位置不是@
if(mark[nx][ny] == true) continue; // 若该位置已经被计算过
mark[nx][ny] = true; // 标记该位置为已经计算
DFS(nx,ny); // 递归查询与该相邻位置直接相邻的点
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
if(n == 0 && m == 0) break;
for(int i = 1 ; i <= n ; i++){
scanf("%s",maze[i]+1); // 第i行地图信息保存在maze[i][1]到maze[i][m]中

}
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= m ; j++){
mark[i][j] = false;
}
}// 初始化所有位置未被计算
int ans = 0; // 初始化块计数器
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= m ; j++){
if(mark[i][j] == true) continue; // 若该位置已被处理,跳过
if(maze[i][j] == '*') continue; // 若该位置不为@,跳过
DFS(i,j); // 递归遍历与其直接或间接相邻的@
ans++; // 答案递增
}
}
printf("%d\n",ans); // 输出
}
return 0;
}

运行结果:

坚持原创技术分享,您的支持将鼓励我继续创作
-------------本文结束感谢您的阅读-------------
0%