算法竞赛入门经典:第七章 暴力求解法 7.7解答树

/*
解答树:
以下的树显示了排列递归函数的调用过程。
                                                            (****)
            (1***)                         (2***)                          (3***)                       (4***)
(12**)    (13**)   (14**)    (21**)  (23**)(24**)         (31**)  (32**)   (34**)        (41**)  (42**)   (43**)
(123*)(124*)
(1234)

特点:
第0层有n个儿子,第一层各节点各有n-1个儿子,第二层各有n-2个儿子,第n层节点没有儿子。每个叶子对应一个排列,共有n!个叶子。这棵树展示的是:
从什么都没做到逐步生成完整解的过程。

解答树特点:多步骤,多选择,用递归
0层:1个节点,1层:n个节点,2层:n*(n-1),第3层:n*(n-1)*(n-2),第n层:n*(n-1)*(n-2)*(n-3)*...*1 = n!个节点。
T(n) = 
多数情况下:解答树上所有节点来源于最后一两层

下一个排列:
枚举所有排列新方法:从字典序最小排列开始,不停调用"求下一个排列"的过程,用C++库函数next_permutation
输入:
3 2 1
1 1 1
输出:
(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2),
(3,2,1)。
1 1 1
*/

/*
关键:
1 		sort(iArr,iArr+n);//调用下一个排列之前必须确保当前排列排序过
		do{
			for(int k = 0 ; k < n ; k++)//等于对于每个元素,输出以其为首的排列。这里调用第一个循环,就是输出最小排列
			{
				//printf("%d",iArr[k]);
				printf("%d ",iArr[k]);
			}
		puts("\n");
		}while(next_permutation(iArr,iArr+n));//下一个排列不为空
2 这里用do while循环的意思是:如果先用while循环,直接漏掉了最小的排列。
*/

#include <stdio.h>
#include <algorithm>

#define MAXSIZE 1024

using namespace std;

void genPermutation()
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		int iArr[MAXSIZE];
		for(int i = 0 ; i < n ; i++)
		{
			scanf("%d",&iArr[i]);
		}
		sort(iArr,iArr+n);//调用下一个排列之前必须确保当前排列排序过
		do{
			for(int k = 0 ; k < n ; k++)//等于对于每个元素,输出以其为首的排列。这里调用第一个循环,就是输出最小排列
			{
				//printf("%d",iArr[k]);
				printf("%d ",iArr[k]);
			}
			puts("\n");
		}while(next_permutation(iArr,iArr+n));//下一个排列不为空
	}
}

int main(int argc,char* argv[])
{
	genPermutation();
	system("pause");
	return 0;
}

你可能感兴趣的:(解答树)