【算法学习笔记】13.暴力求解法01 枚举排列

所谓暴力求解法,大意应该是根据提议分析出的所有可能的情况(优化过的研究域)来一一研究,得到最终结果

第一节呢就是枚举排列

这里的排列指的是一个集合的元素中根据字典序进行排列。用wikioi的一道题来进行解释吧

样例输入 Sample Input
3
样例输出 Sample Output
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1 

此排列的生成过程可以认为是 第一位从1开始进行, 而第二位从可能的最小的数开始遍历,第三位又是在第二位的基础上从可能的最小的数上继续变化。

这里说白了就是一个递归过程。

1.得到已经排完的序列a,以及cur表示当前进行到的位置(从0开始计数)

2.从此序列中得到可能的数(不重复),从其中进行下一次排列

void pailie(int* a,int cur)
{
	int i,j,k,ok;
	//如果cur == n 表面 a已经到了尽头 开始打印序列 (递归边界)
	if(cur==n)	
	{
		for(k=0;i<n;i++) 
			printf("%d ",a[i]);//printf 的效率比cout快不少呢
		printf("\n");
		return;
	} 
	for(i=1;i<=n;i++)
	{ 
		ok=1;//设定标志变量
		for(j=0;j<cur;j++)	if(a[j]==i)	
		{
			ok=0;	break;//找到了一个还没有在a中出现的最小的元素用来打头
		} 
		if(ok)
		{
			a[cur]=i;//打头
			pailie(a,cur+1);//打头之后后面继续走,此时的已排好的序列中已经包含了i 光标也前进了一位
		}
	}
		
}
之后调用pailie(ans,0);即可
这里用递归来处理是非常好的选择,STL库也提供了一个方法, 就是用不断根据上一个序列生成下一个序列的思维方式来处理问题

首先我们要获得一个最字典序的排列,用sort函数就可以了

然后用do while循环来调用next_permutation 这样的好处是哪怕只有一个排列也可以处理了、

核心代码如下


#include <algorithm>
<span style="white-space:pre">	</span>int p[4]={1,4,2,2};
	int n=4;
	
	sort(p,p+n);//不知道内部实现到底是什么 = =  凑合用吧stl应该不会坑人
	do
	{
		for(int i=0;i<n;i++) 
			printf("%d ",p[i]);
		printf("\n");	
	}while(next_permutation(p,p+n));

下面来说说怎么处理可重复的排列。(书上说next_permutation可以用来处理重复序列可是我发现不好使呀~ 不知道那里设置错了,以后再来解决) 

已经解决,原年是对重复排列的理解出现了错误

那么就在递归的方法上进行加工。

in

4
1 2 3 2

out
1 2 2 3
1 2 3 2
1 3 2 2
2 1 2 3
2 1 3 2
2 2 1 3
2 2 3 1
2 3 1 2
2 3 2 1
3 1 2 2
3 2 1 2
3 2 2 1  

这里我们就要考虑几个细节问题。

比如 如何区分重复了的元素,使得排列数量保持正确 这就需要我们记录某一种元素在已经拍完的序列A中出现的次数c1,和总集合的中的个数c2

只要c1<c2 说明还有可以排的元素,所以要继续递归。


void pailie(int* a,int cur) 
{
	int k;
	//如果cur == n 表面 a已经到了尽头
	if(cur==n)	
	{
		for(int i=0;i<n;i++) 	printf("%d ",a[i]);
		putchar('\n');
		return;
	} 
	for(int i=0;i<n;i++)//如果是i=0即第一个元素 则直接进入处理 因为他肯定没有被重复,如果是第2个开始则需要进行筛选
	if(!i||p[i]!=p[i-1]){ 
		int c1 = 0, c2 = 0;
	    for(int j=0; j<cur; j++) if(a[j] == p[i]) c1++;
	    for(int j=0; j<n; j++) if(p[j] == p[i]) c2++;
	    if(c1 < c2) {
	      a[cur] = p[i];//将元素充入排列中 
	      pailie2(a, cur+1);
	    }
	} 
}


总体上大概就是如此



你可能感兴趣的:(学习笔记)