第一题
思路
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;
}
}
}
题目二
思路
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);
}
}