递归与回溯问题

1. 题目描述:输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来
输入描述:每个测试输入包含2个整数,n和m
输出描述:按每个组合的字典序排列输出,每行输出一种组合
示例1
输入
5 5
输出
1 4
2 3
5
解答

#include<iostream>
#include<vector>
using namespace std;

void print(int m,int n,int beg,vector<int>&v)
{
    if (m==0) {
        for (int i = 0; i < v.size(); i++) {
            i == 0 ? cout << v[i] : cout << " " << v[i];
        }
        cout << endl;
    }
    for (int start = beg; start <= n&&start<=m; start++) {
            v.push_back(start);
            print(m-start,n,start+1,v);
            v.pop_back();
    }
}

int main()
{
    int n, m;
    cin >> n >> m;
    vector<int>v;
    print(m,n,1,v);
    return 0;
}

2. 题目描述:有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。
输入描述:输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。
输出描述:输出包括一行,为走法的数目。

示例1
输入
3 2

输出
10

解法:

#include<iostream>
using namespace std;

int get_ways(int x,int y)
{
    if(x==1 && y==0)return 1;
    if(x==0 && y==1)return 1;
    if(x==0)return get_ways(x,y-1);
    if(y==0)return get_ways(x-1,y);
    else
        return get_ways(x-1,y)+get_ways(x,y-1);
}

int main()
{
    int m,n;
    cin>>m>>n;
    cout<<get_ways(m,n);
}

3. 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的3x4的矩阵中包含一条字符串“bcced”的路径(路径中的字母用斜体表示)。但矩阵中不包含字符串“abcb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
a    b    c    e
s    f    c    s
a    d    e    e

解法

bool hasPathCore(vector<vector<char>>&map, int m, int n, int i, int j, string &s, int pathLen,
	vector<vector<int>>&visited)
{
	if (s.size() == pathLen)
		return true;
	bool hasPath = false;
	if (i >= 0 && i < m && j >= 0 && j < n && map[i][j] == s[pathLen] && !visited[i][j]) {
		++pathLen;
		visited[i][j] = true;
		hasPath = hasPathCore(map, m, n, i, j - 1, s, pathLen, visited) ||
			hasPathCore(map, m, n, i - 1, j, s, pathLen, visited) ||
			hasPathCore(map, m, n, i, j + 1, s, pathLen, visited) ||
			hasPathCore(map, m, n, i + 1, j, s, pathLen, visited);
	
		if (!hasPath) {
			--pathLen;
			visited[i][j] = false;
		}	
	}
	return hasPath;
}
bool hasPath(vector<vector<char>>&map, string &s)
{
	int m = map.size(), n = map[0].size();
	vector<vector<int>>visited(m,vector<int>(n,0));
	int pathLen = 0;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (hasPathCore(map, m, n, i, j, s, pathLen, visited)) {
				return true;
			}
		}
	}
	return false;
}

4. 题目:地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人都够进入方格(35,37),因为3+5+3+7=18.但它不能进入方格(35,38),因为3+5+3+8=19。请问该机器人能够到达多少个格子?
解法
 

int getDigitSum(int num) {
	int sum = 0;
	while (num > 0) {
		sum += num % 10;
		num /= 10;
	}
	return sum;
}
bool check(int threshold,int m,int n,int i,int j, vector<vector<int>>&visited) {
	if (i >= 0 && i < m&&j >= 0 && j < n&&getDigitSum(i) + getDigitSum(j) <= threshold && !visited[i][j]) {
		return true;
	}
	return false;
}
int movingCount(int threshold, int m, int n, int i, int j, vector<vector<int>>&visited)
{
	int count = 0;
	if (check(threshold, m, n, i, j, visited)) {
		visited[i][j] = true;
		count = 1 + movingCount(threshold, m, n, i - 1, j, visited) +
			movingCount(threshold, m, n, i, j - 1, visited) +
			movingCount(threshold, m, n, i + 1, j, visited) +
			movingCount(threshold, m, n, i, j + 1, visited);
	}
	return count;
}
int movingCount(int threshold, int m, int n)
{
	vector<vector<int>>visited(m,vector<int>(n,0));
	int count = movingCount(threshold,m,n,0,0,visited);
	return count;
}

.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值