回溯求解排列组合的关键在于两点:
一是要明白回溯的思想到底是什么
二是要考虑清楚什么时候进行向下探索,什么时候碰壁回头,什么时候到达回溯的重点,退出循环。也就是回溯过程中的约束条件
回溯思想:向前走,碰壁回头
回溯的一般形式如下:
以求解排列A(n,m)为例,这里解释一下排列的约束条件:
1.第一个约束条件就是选出的数不一样。
2.每一个数都小于等于n。
3.选够m个数即进行输出。
4.向下探索,向上回溯。
至于组合,只需要在排列的第一个条件上加上一个固有的顺序要求就o了。
运行截图:
源码这里暂时不予给出,有需要的话,可以评论区留下自己的邮箱。(因为是作业,害怕自己出现类同代码。)
预计11月底,进行给出。
二更:
源码附上:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//求解A(n,m);
void PaiLie(int m,int n); //排列
void ZuHe(int m,int n); //组合
int main()
{int m,n;cout<<"Input n m:";cin>>n>>m;PaiLie(n,m);ZuHe(n,m);
}void PaiLie(int m,int n) //排列 A(m,n)
{int a[100]={0};int i=1;int count=0; //计算总长度 a[i]=1;while(1){int flag=1;for(int j=1;j<i;j++) {if(a[i]==a[j]) //不满足约束条件,标志位置零 {flag=0;break;}}if(flag&&i<n) //向下探索 {i++;a[i]=1;continue;} if(flag&&i==n) //满足条件进行输出 {for(int j=1;j<=n;j++){if(j<n){cout<<a[j]<<",";}if(j==n){cout<<a[j]<<endl;} }count++;}while(a[i]==m&&i>1) //向上回溯 {i--;}if(i==1&&a[i]==m) //回溯到头了,退出循环 {break;} else //本阶段继续探索 {a[i]++;}}cout<<"回溯 排列个数:"<<count<<endl;
}
void ZuHe(int m,int n) //组合
{int a[100]={0};int i=1;int count=0;a[i]=1;while(1){int flag=1;for(int j=1;j<i;j++) { if(a[i]>=a[j]) //不满足约束条件,标志位清零 {flag=0;break;}}if(flag&&i<n) //数量不够,继续向下探索 {i++;a[i]=1;continue; }if(flag&&i==n) //满足条件,进行输出 {for(int j=1;j<=n;j++){if(j<n){cout<<a[j]<<",";}if(j==n){cout<<a[j]<<endl;}}count++;}while(a[i]==m&&i>1) //向上回溯 {i--;}if(a[i]==m&&i==1) //回溯到头,退出回溯 {break; }else{a[i]++; //在当前阶段继续回溯 }} cout<<"回溯 组合个数:"<<count<<endl;
}