回溯法求排列问题
2012-07-15 20:09 youxin 阅读(969) 评论(0) 编辑 收藏 举报问题:
输出n的全排列
1. 问题描述: 输出自然数1到n的所有不重复的排列,即n的全排列。
2. 问题分析:
(1) 解空间: n的全排列是一组n元一维向量(x1, x2, x3, ... , xn),搜索空间是:1<=xi<=n i=1,2,3,...,n
(2) 约束条件: xi互不相同。技巧:采用"数组记录状态信息", 设置n个元素的一维数组d,其中的n个元素用来记录数据1-n的使用情况,已经使用置0,未使用置1
#include<iostream> #include<memory> using namespace std; int count=0;//解个数 int n;//输入数据 int *a ;//解向量 int *d ;//解状态 void clear( ) { for(int i=1;i<=n+1;i++) { d[i]=0; } } void output()//第0个不存 { for(int i=1;i<=n;i++) cout<<a[i]<<ends; cout<<endl; }
void tryArrangement(int k) { for(int i=1;i<=n;i++) { if(d[i]==0) { a[k]=i; d[i]=1; } else { //表明已用过 continue; } if(k<n) //没搜索到底 { tryArrangement(k+1); } else { count++; output(); } d[a[k]]=0; //回溯 } } int main() { cin>>n; a=new int[n+5];//解向量 d=new int[n+5];//解状态 clear( ); tryArrangement(1); }
最开始是这样置d[ ]为0的:
memset(d,0,sizeof(d));
不行,为什么?
记住,memset是按字节赋值的,第3个参数指定要赋值的字节的大小,应该改成:
memset(d,0,sizeof(int)*n);
算法说明:k为当前处理的第k个元素。上面的复杂度为O(n^n),不是一个好的算法,因此不可能用它去搜索排序树。
调试分析
k=1 if(d[1]==0) true a[1]=1; d[1]=1 try(2)
k=2 if(d[2]==0) a[2]=2 d[2]=1 try(3)
k=3 if(d[3]==0) a[3]=3; d[3]=1;
3==n; count=1; output 1 2 3
d[3]=0;
} 跳到for( )处运行 F11运行都函数末尾,
F11又跳到try(3) k=2 d[a[2]]=0
} 跳到For处运行
if(d[3]==0) a[2]=3 d[3]=1;
if(k<3) try(3)
我的代码:
void perm(int n,int r) { int k=1; a[k]=0; while(k>0) { a[k]=a[k]+1; while(a[k]<=n && !check(k)) { a[k]++; } if(a[k]<=n) { if(k==n) { for(int i=1;i<=n;i++) cout<<a[i]<<ends; cout<<endl; count++; } else { k++; a[k]=0; } } else { a[k]=0; k--; } } }
可以输出全部排列。
另一种解法==也是搜索排列树的算法框架。
设计:根据全排列的概念,定义数组初始值为(1,2,3,4,。。n),这是全排列的一种结果,然后通过数据间的交换,则可产生所有不同的排列:
#include<iostream> using namespace std; int a[100],n,s=0; void output() { for(int j=1;j<=n;j++) cout<<a[j]<<ends; cout<<endl; } void tryArrange(int k) { int j; if(k>n) { output(); } else for(j=k;j<=n;j++) { swap(k,j); tryArrange(k+1); swap(k,j); //回溯时,恢复原来的排列 } } int main() { int i; cin>>n; for(i=1;i<=n;i++) a[i]=i; tryArrange(1); cout<<"换行符"<<"s="<<s; }
注意c++try是关键字。swap在ios文件中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通