您的位置:首页 > 其它

回溯法求排列问题

2012-07-15 20:09 155 查看
问题:

输出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文件中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: