上一道回溯基础题(虽然我第一次做这道题花了好久):
【题目部分】
列出所有从数字式1到数字n的连续自然数的排列,要求所产生的任一数字序列中不允许出现重复的数字。
Input
n(1<=n<=9)
Output
由1~n组成的所有不重复的数字序列,每行一个序列,每个数字场宽为5。
Sample Input 1
3
Sample Output 1
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
这是一道极其经典的回溯算法的入门题,回溯算法的一般解题步骤有:
1、确定解空间。(根据题意确定解的存储结构,是用数组存储?还是用一个变量存储?等等)
2、归纳出解空间的搜索范围?搜索条件?
3、确定递归的入口参数
4、确定递归的出口条件。到出口需要做什么?
以本题为例来讲一讲解题步骤:
1、解用1..n的数组存储
2、对数组的每个单元填值,假设当前位置为pos,要填的值为i,则 1≤ i ≤ n ,并且i在1-- pos-1 单元没有出现过
3、一个单元填完,就直接移到下一个单元,所以递归的入口参数只需要一个位置信息
4、递归出口一般跟入口参数有关。当所有单元都填好了就不要继续往下递归。本题要求输出每个序列,所以到递归出口时需要输出解
明白了吗,不用明白了我直接上代码:
#include<bits/stdc++.h>
using namespace std;
int n;
bool b[10];//题目已规定n<10
int a[10];//同上
void print(){//负责打印(打工)的函数qwq
for(int i=1;i<=n;i++)
cout<<setw(5)<<a[i];
cout<<endl;
return ;//返回
}
void DFS(int k){//回溯
if(k==n+1)//如果已经选了n+1个数,那就输出
print();
for(int i=1;i<=n;i++){
if(!b[i]){//如果这个数没使用过
b[i]=1;//把它标记一下抓来打工
a[k]=i;//储存(打工)
DFS(k+1);//继续挑选下一个数
b[i]=0;//回溯一步
}
}
return ;//终止回溯
}
int main(){
std::ios::sync_with_stdio(false);//加快cin和cout
cin>>n;
DFS(1);
return 0;//养成好习惯
}
( ^_^ )/~~拜拜