数据结构和算法设计专题之---24点游戏(穷举法和递归法)

一个简单的24点程序

下面本文将通过两个题目实例,分别给出用递归方法和循环方法的解决方案以及解题思路,便于读者更好地掌握两种方法。首先是一个简单的计算24点的问题(为了简化问题,我们假设只使用求和计算方法):

19中任选四个数字(数字可以有重复),使四个数字的和刚好是24

题目很简单,数字都是个位数,可以重复且之用加法,循环算法的核心就是使用四重循环穷举所有的数字组合,对每一个数字组合进行求和,判断是否是24。使用循环的版本可能是这个样子:

8constunsignedintNUMBER_COUNT=4;//9

9constintNUM_MIN_VALUE=1;

10constintNUM_MAX_VALUE=9;

11constunsignedintFULL_NUMBER_VALUE=24;//45;

40voidPrintAllSResult(void)

41{

42inti,j,k,l;

43intnumbers[NUMBER_COUNT]={0};

44

45for(i=NUM_MIN_VALUE;i<=NUM_MAX_VALUE;i++)

46{

47 numbers[0]=i;/*确定第一个数字*/

48 for(j=NUM_MIN_VALUE;j<=NUM_MAX_VALUE;j++)

49 {

50 numbers[1]=j;/*确定第二个数字*/

51 for(k=NUM_MIN_VALUE;k<=NUM_MAX_VALUE;k++)

52 {

53 numbers[2]=k;/*确定第三个数字*/

54 for(l=NUM_MIN_VALUE;l<=NUM_MAX_VALUE;l++)

55 {

56 numbers[3]=l;/*确定第四个数字*/

57 if(CalcNumbersSum(numbers,NUMBER_COUNT)==FULL_NUMBER_VALUE)

58 {

59 PrintNumbers(numbers,NUMBER_COUNT);

60 }

61 }

62 }

63 }

64}

65}

这个PrintAllSResult()函数看起来中规中矩,但是本人的编码习惯很少在一个函数中使用超过两重的循环,更何况,如果题目修改一下,改成9个数字求和是45的组合序列,就要使用9重循环,这将使PrintAllSResult()函数变成臭不可闻的垃圾代码。

现在看看如何用递归方法解决这个问题。递归方法的解题思路就是对题目规模进行分解,将四个数字的求和变成三个数字的求和,两个数字的求和,当最终变成一个数字时,就达到了递归终止条件。这个题目的递归解法非常优雅:

67voidEnumNumbers(int*numbers,intlevel,inttotal)

68{

69inti;

70

71for(i=NUM_MIN_VALUE;i<=NUM_MAX_VALUE;i++)

72{

73 numbers[level]=i;

74 if(level==(NUMBER_COUNT-1))

75 {

76 if(i==total)

77 {

78 PrintNumbers(numbers,NUMBER_COUNT);

79 }

80 }

81 else

82 {

83 EnumNumbers(numbers,level+1,total-i);

84 }

85}

86}

87

88voidPrintAllSResult2(void)

89{

90intnumbers[NUMBER_COUNT]={0};

91

92 EnumNumbers(numbers,0,FULL_NUMBER_VALUE);

93}

如果题目改成“9个数字求和是45的组合序列”,只需将NUMBER_COUNT的值改成9FULL_NUMBER_VALUE的值改成45即可,算法主体部分不需做任何修改。

你可能感兴趣的:(数据结构和算法设计专题之---24点游戏(穷举法和递归法))