第5章-递归及应用
文章目录
1. 二进制转换为十进制【中等】
请用递归的方式实现二进制向十进制转换。
【输入】 二进制序列,长度小于20
【输出】 二进制对应的10进制数
例如:
【输入】111001
【输出】57
#include <iostream>
#define maxlen 21
using namespace std;
long two_to_ten(char *s, long sum)
{
if (*s == '\0')
return sum;
else {
sum = sum * 2 + (*s - '0');
two_to_ten(s + 1, sum);
}
}
int main()
{
char s[maxlen] = {'\0'};
cin >> s;
cout << two_to_ten(s, 0);
return 0;
}
2. Letter Combinations of a Phone Number【中等】
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
2->abc
3->def
4->ghi
5->jkl
6->mno
7->pqrs
8->tuv
9->wxyz
数字对应字母的图片
【输入】 2-9之间的数字串,长度不超过10,
【输出】 数字串对应的所有字母组合
例如:
【输入】
23
【输出】
ad ae af bd be bf cd ce cf
【输入】
22
【输出】
aa ab ac ba bb bc ca cb cc
#include <iostream>
#include <vector>
using namespace std;
void Combination(string digits, int level, vector<string>& results, string dict[], string curr) {
if (level == digits.size()) {
results.push_back(curr);
return;
}
int index = digits[level] - '0';
string tmp = dict[index];
for (int i = 0; i < tmp.size(); i++) {
string next = curr + tmp[i];
Combination(digits, level + 1, results, dict, next);
}
}
vector<string> letterCombinations(string digits) {
vector<string> results;
if (digits.size() <= 0) return results;
string dict[] = { "", "", "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
Combination(digits, 0, results, dict, "");
return results;
}
int main()
{
string a;
cin >> a;
vector<string> b = letterCombinations(a);
int len = b.size();
for (int i=0; i < len; i++) {
cout << b[i] << ' ';
}
return 0;
}
3. n个数的全排列【中等】
给定整数n,n<=10,请求出n的全排列。
N=3时,1-3的排列可以为:
1:1 2 3
2:1 3 2
3:2 1 3
4:2 3 1
5:3 1 2
6:3 2 1
一共有6种情况
【输入】 整数n,n<=20
【输出】
1-n的排列 (排列数大于10的,仅输出前10组即可)
总的全排列数
例如:
【输入】 4
【输出】
1:1 2 3 4
2:1 2 4 3
3:1 3 2 4
4:1 3 4 2
5:1 4 2 3
6:1 4 3 2
7:2 1 3 4
8:2 1 4 3
9:2 3 1 4
10:2 3 4 1
24
#include <iostream>
using namespace std;
int n, cnt = 1;
long long sum = 1;
int arr[21] = { 0 };//保存每次输出的数组
int record[21] = { 0 };//记录一个数是否在数组里
void quanpailie(int num)
{
if (cnt > 10) {
return;
}
if (num == n + 1) {
cout << cnt << ':';
for (int i = 1; i <= n; i++) {
cout << arr[i] << ' ';
}
cout << endl;
cnt++;
return;
}
for (int i = 1; i <= n; i++) {
if (record[i] == 0) {//如果i没有在数组里面
arr[num] = i;//填上i
record[i] = 1;//i已经进入数组
quanpailie(num + 1);//填下一个位置
arr[num] = 0;
record[i] = 0;//把i收回,试下面一个数
}
}
return;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
sum *= i;
}
quanpailie(1);
cout << sum;
return 0;
}
4. A Maze Problem【中等】
A maze is to be represented by a 12*12 array composed of three values: Open, Wall, or Exit. There is one exit from the maze. Write a program to determine whether it is possible to exit the maze from the starting point (any open square can be a starting point). You may move vertically and horizontally to any adjacent open square(左右上下四个方向). You may not move to a square containing a wall. The input consists of a series of 12 lines of 12 characters each, representing the contents of each square in the maze. The characters are O, W, or E.
【输入】 12×12的迷宫方阵,每个格子的可能取值有:O, W, or E,输入数据能够确保迷宫只有一个出口。
任意3个起点的坐标,格式如下(x,y)。其中x为纵坐标,y为横坐标,起始坐标从左上角的格子开始,坐标起始值为0.
【输出】
起点到出口的最短路径长度(经过多少个方格),若起点无法到达出口则输出-1。起始节点和结束节点都算入路径长度的计算。
例如:
【输入】
O W O W O W O O W O W O
O W O W W W W O W O O E
O W W W O O O O O O O O
W W W O O O O W W W O W
O O O O W W W O O O O O
O O W O W O W O W O W W
O W W O O O W W O O O W
O O W O O W W W O O O O
O O O W O O O O W W W W
W W W O O O O W W W O O
O W W W W O O O O O W W
W W W O O O O O W W W W
(0,0) (5,7) (7,8)
【输出】
-1 9 10
【解释】
输出表示第一个点(0,0)无法到达出口;
第二个点(5,7)到达出口的最短路径是9;
第三个点(7,8)到达出口的最短路径是10。
注:
- 这道题输入的时候字母中间没有空格。
- 我采用的加墙方法被助教一顿吐槽,建议用下标判断是否越界。
#include <iostream>
#include <cstdio>
const int max_maze = 12;
using namespace std;
class Maze
{
public:
Maze();
void creat_maze(int max_maze);
void creat_judge();
int get_flag();
int get_step();
void dfs(int x, int y, int step);
private:
int min, flag;
char MAZE[max_maze + 2][max_maze + 2];
int judge[max_maze + 2][max_maze + 2];
};
Maze::Maze()
{
}
void Maze::creat_maze(int max_maze)
{
int i, j;
char a;
//加墙
for (i = 0; i < max_maze + 2; i++) {
MAZE[0][i] = 'W';
MAZE[max_maze + 2][i] = 'W';
MAZE[i][0] = 'W';
MAZE[i][max_maze + 2] = 'W';
}
//输入
for (i = 1; i <= max_maze; i++) {
for (j = 1; j <= max_maze; j++) {
cin >> a;
MAZE[i][j] = a;
}
}
}
void Maze::creat_judge()
{
flag = 0;
min = max_maze * max_maze;
int i, j;
for (i = 1; i <= max_maze; i++) {
for (j = 1; j <= max_maze; j++)
judge[i][j] = 0;
}
}
int Maze::get_flag()
{
return flag;
}
int Maze::get_step()
{
return min;
}
void Maze::dfs(int x, int y, int step)
{
//终点时
if (MAZE[x][y] == 'E') {
if (step < min) {
min = step;
flag = 1;
}
return;
}
//不是终点时,顺时针试探
//不要忘了判断E,当走到邻点是E的时候只判断O是进不去递归函数的
//右
if ((MAZE[x][y + 1] == 'O' || MAZE[x][y + 1] == 'E') && judge[x][y + 1] == 0) {
//可以向右时,设置为已访问
judge[x][y + 1] = 1;
dfs(x, y + 1, step + 1);
//回溯时,右边设置为未访问
judge[x][y + 1] = 0;
}
//下
if ((MAZE[x + 1][y] == 'O' || MAZE[x + 1][y] == 'E') && judge[x + 1][y] == 0) {
judge[x + 1][y] = 1;
dfs(x + 1, y, step + 1);
judge[x + 1][y] = 0;
}
//左
if ((MAZE[x][y - 1] == 'O' || MAZE[x][y - 1] == 'E') && judge[x][y - 1] == 0) {
judge[x][y - 1] = 1;
dfs(x, y - 1, step + 1);
judge[x][y - 1] = 0;
}
//上
if ((MAZE[x - 1][y] == 'O' || MAZE[x - 1][y] == 'E') && judge[x - 1][ y] == 0) {
judge[x - 1][y] = 1;
dfs(x - 1, y, step + 1);
judge[x - 1][y] = 0;
}
return;
}
int main()
{
int x, y;
Maze a;
a.creat_maze(max_maze);
for (int i = 0; i < 3; i++) {
char c;
cin >> c >> x >> c >> y >> c;
a.creat_judge();
a.dfs(x + 1, y + 1, 1);//因为外面加墙了所以要错开
if (a.get_flag()) {
cout << a.get_step() << ' ';
}
else cout << -1 << ' ';
//getchar();
}
return 0;
}