算法竞赛入门经典:第七章 暴力求解法 7.6可重复的排列

 

/*
生成可重集得到排列:
把问题改成:输入数组P,并按字典序输出数组A各元素的所有全排列,则需要对上述程序进行修改--把P加到printPermutation的参数列表中,然后把
代码中的if(iArr[i] == j) 和if(A[pos] == j)改成if(iArr[i] == P[j]) 和 iArr[pos] = P[j]
bug1:如果数组中是重复的元素 1 1 1的话 ,因为禁止出现重复,造成错误
解决方法:统计iArr[0]~iArr[pos-1]中P[i]的出现次数c1,以及P数组中P[i]出现的次数c2。只要c1<c2,就可以递归
bug2:如果111重复,也输出27次。枚举的下标应该不重复,不遗漏取遍所有p[i]值。只需检查p的第一个元素和所有前一个元素不相同。
思路:



*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 1024

void printPermutation(int* iArr,int pos,int n,int* iPer)
{
	if(pos == n)
	{
		for(int k = 0 ; k < n;k++)
		{
			printf("%d ",iArr[k]);
		}
		printf("\n");
		return;
	}
	for(int i = 0;i < n;i++)
	{
		if(!i || iPer[i] != iPer[i-1])//判断当前元素与前面元素不能重复,否则遇111这种数组,会有重复输出
		{
			//统计iArr[0]到iArr[pos-1]中iPer[i]出现的次数
			int iCount1 = 0;
			for(int j = 0; j < pos;j++)
			{
				if(iArr[j] == iPer[i])
				{
					iCount1++;
				}
			}
			int iCount = 0;
			//统计iPer[i]在数组中出现次数
			for(int m = 0; m < n ;m++)
			{
				if(iPer[i] == iPer[m])
				{
					iCount++;
				}
			}
			//if(!isAppear)
			if(iCount1 < iCount)//判断重复的条件应该改成出现次数的判断
			{
				iArr[pos] = iPer[i];//把第iPos个元素确定下来之后进行后续递归
				printPermutation(iArr,pos+1,n,iPer);
			}
		}
	}
}


int main(int argc,char* argv[])
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		int iArr[MAXSIZE];
		int iPer[MAXSIZE];
		int j = 0;
		for(int i = 0; i < n;i++)
		{
			scanf("%d",&iPer[j++]);
		}
		printPermutation(iArr,0,n,iPer);
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(排列)