引子
1.关于深搜:深度优先搜索是一种解决问题的算法策略。通常,首先它把问题解决过程分解成若干个阶段,然后递归地搜索(枚举)每个阶段所有可能的选项,得到组合式的解,到达边界后,检验解的合法性。
2.学习了那么久的深搜,再回头看一下,就是一串格子,按照题目的要求去填空,其本质就是求组合与排列。
3.算法框架:
void dfs(int i)
{
if(满足边界条件)
{
输出解
return;
}
for(可选择的选择j)
if(没有访问过j&&其它条件)
{
标记j已经访问过
保存
dfs(i+1);
取消标记//回溯
}
}
正题
排列
生成n维向量vector
n维向量是有n个元素的序对,每个元素的取值范围从1到k。例如3的5维向量为{1,1,1,1,1},{1,1,1,1,2},….,{3,3,3,3,3}。输入k和n,输出所有k的n维向量。 、
限制条件 :1<= k <=10, 1<=n<=6
分析
简单的一个搜索,直接用框架解决,而且元素可以重复,不用标记
#include<cstdio>
#define MAXN 6
int n,k,a[MAXN+5];
void dfs(int i)
{
if(i>n)
{
for(int j=1;j<n;j++)
printf("%d ",a[j]);
printf("%d\n",a[n]);
return ;
}
for(int j=1;j<=k;j++)
{
a[i]=j;
dfs(i+1);
}
}
int main()
{
scanf("%d %d",&n,&k);
dfs(1);
}
思考
- 这道题如果要输出序号,可以增加一个变量tot,like this:
#include<cstdio>
#define MAXN 6
int n,k,a[MAXN+5],tot;
void dfs(int i)
{
if(i>n)
{
tot++;
for(int j=1;j<n;j++)
printf("%d:%d ",tot,a[j]);
printf("%d\n",a[n]);
return ;
}
for(int j=1;j<=k;j++)
{
a[i]=j;
dfs(i+1);
}
}
int main()
{
scanf("%d %d",&n,&k);
dfs(1);
}
2.k的n维向量的总方案数是多少?
对于每一个位置i,都有k个选择,一共n个位置,所以方案数应是k^n
全排列
输入n,输出数字1..n的所有排列。这里不是要计算排列有多少种,而是枚举所 有