【暴力】递归+回溯

0 阅读1分钟

第一题

image.png

思路

1.像这种全排列问题就是递归回溯经典模板,因为正常做法就是套很多层循环,太麻烦所以直接递归+回溯就可以,也叫做记忆化搜索 2.既然知道了需要用到递归,那么我们就要思考我们要递归什么。我们选择递归三个格子,逐渐填满。

难在哪

1.dfs函数最后两行代码困扰了我很久。后来能明白递归到下一个格子的时候,要取消那个数字已经填进去的状态,需要拿回来重新排列

我的代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int n;
int a[10], vis[10];

void dfs(int step);
int main()
{
	scanf("%d", &n);
	dfs(1);



	return 0;
}

void dfs(int step)
{
	if (step > n) {
		for (int i = 1; i <= n; i++) {
			printf("%5d", a[i]);
			
		}
		printf("\n");
		return;
	}

	for (int i = 1; i <= n; i++) {
		if (vis[i] == 0) {
			a[step] = i;
			vis[i] = 1;

			dfs(step + 1);

			vis[i] = 0;
		}
	}
}

题目二

image.png

思路

1.这里明显就是组合问题,和排列不同,那么这里肯定就要引入一个start_index来确定第一个数字然后递增排列。

易错点

1.dfs函数print后不return; 2.组合情况不设数组path; 3.递归把dfs(step+1,i+1)写成dfs(step+1,start+1)。其实start=i+1,别搞错了

我的代码

#include<stdio.h>

void dfs(int step, int start);
int path[22],n,r;
int main()
{
	scanf_s("%d %d", &n, &r);

	dfs(1,1);

	return 0;
}

void dfs(int step, int start) {
	if (step > r) {
		for (int i = 1; i <= r; i++) {
			printf("%3d", path[i]);
		}
		printf("\n");
		return;
	}

	for (int i = start; i <= n; i++) {
		path[step] = i;

		dfs(step + 1, i + 1);
	}
}