﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Way,Method,Algorithm-文章分类-思想火花</title><link>http://www.cppblog.com/yaowf99/category/3291.html</link><description>算法的世界</description><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 09:43:55 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 09:43:55 GMT</pubDate><ttl>60</ttl><item><title>24点递归算法及C语言代码【网上收集】</title><link>http://www.cppblog.com/yaowf99/articles/16623.html</link><dc:creator>Whale</dc:creator><author>Whale</author><pubDate>Tue, 19 Dec 2006 12:45:00 GMT</pubDate><guid>http://www.cppblog.com/yaowf99/articles/16623.html</guid><wfw:comment>http://www.cppblog.com/yaowf99/comments/16623.html</wfw:comment><comments>http://www.cppblog.com/yaowf99/articles/16623.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yaowf99/comments/commentRss/16623.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yaowf99/services/trackbacks/16623.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Courier New">24点算法代码（C语言版本）：<br />int Search(int n, int iGroup)<br />{<br />      /*~~~~~~~~~~*/<br />      int  i, j;<br />      double a, b;<br />      char expa[MAX_LENGTH_OF_EXP];<br />      char expb[MAX_LENGTH_OF_EXP];<br />      /*~~~~~~~~~~*/<br />      if(1 == n)<br />      {<br />              if(fabs(number[iGroup][0] - NUMBER_TO_BE_CAL) &lt; PRECISION)<br />              {<br />                     return 1;<br />              }<br />              else<br />              {<br />                     return 0;<br />              }<br />       }<br /></font>
				<font face="Courier New">       for(i = 0; i &lt; n; i++)<br />       {<br />           for(j = i + 1; j &lt; n; j++)<br />           {<br />               strcpy(expa, expression[i]);<br />               strcpy(expb, expression[j]);<br />               a = number[iGroup][i];<br />               b = number[iGroup][j];<br />            <br />               number[iGroup][j] = number[iGroup][n - 1];<br />               strcpy(expression[j], expression[n - 1]);</font>
		</p>
		<p>
				<font face="Courier New">               sprintf(expression[i], "(%s+%s)", expa, expb);<br />               number[iGroup][i] = a + b;<br />            <br />               if(Search(n - 1, iGroup))<br />               {<br />                   return 1;<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               sprintf(expression[i], "(%s-%s)", expa, expb);<br />               number[iGroup][i] = a - b;<br />               if(Search(n - 1, iGroup))<br />               {<br />                   return 1;<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               sprintf(expression[i], "(%s-%s)", expb, expa);<br />               number[iGroup][i] = b - a;<br />               if(Search(n - 1, iGroup))<br />               {<br />                   return 1;<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               sprintf(expression[i], "(%s*%s)", expa, expb);<br />               number[iGroup][i] = a * b;<br />               if(Search(n - 1, iGroup))<br />               {<br />                   return 1;<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               if(b != 0)<br />               {<br />                   sprintf(expression[i], "(%s/%s)", expa, expb);<br />                   number[iGroup][i] = a / b;<br />                   if(Search(n - 1, iGroup))<br />                   {<br />                       return 1;<br />                   }<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               if(a != 0)<br />               {<br />                   sprintf(expression[i], "(%s/%s)", expb, expa);<br />                   number[iGroup][i] = b / a;<br />                   if(Search(n - 1, iGroup))<br />                   {<br />                       return 1;<br />                   }<br />               }</font>
		</p>
		<p>
				<font face="Courier New">               number[iGroup][i] = a;<br />               number[iGroup][j] = b;<br />               strcpy(expression[i], expa);<br />               strcpy(expression[j], expb);<br />           }<br />       }<br /> return 0;<br />}</font>
		</p>
		<p>
				<font face="Courier New">
						<u>基本原理</u>
						<br />基本原理是穷举4个整数所有可能的表达式，然后对表达式求值。</font>
		</p>
		<p>
				<font face="Courier New">表达式的定义： expression = (expression|number) operator (expression|number)</font>
		</p>
		<p>
				<font face="Courier New">因为能使用的4种运算符 + - * / 都是2元运算符，所以本文中只考虑2元运算符。<br />2元运算符接收两个参数，输出计算结果，输出的结果参与后续的计算。</font>
		</p>
		<p>
				<font face="Courier New">由上所述，构造所有可能的表达式的算法如下：</font>
		</p>
		<p>
				<font face="Courier New">(1) 将4个整数放入数组中<br />(2) 在数组中取两个数字的排列，共有 P(4,2) 种排列。对每一个排列，<br />(2.1) 对 + - * / 每一个运算符，<br />(2.1.1) 根据此排列的两个数字和运算符，计算结果<br />(2.1.2) 改表数组：将此排列的两个数字从数组中去除掉，将 2.1.1 计算的结果放入数组中<br />(2.1.3) 对新的数组，重复步骤 2<br />(2.1.4) 恢复数组：将此排列的两个数字加入数组中，将 2.1.1 计算的结果从数组中去除掉</font>
		</p>
		<p>
				<font face="Courier New">可见这是一个递归过程。步骤 2 就是递归函数。当数组中只剩下一个数字的时候，这就是表达式的最终结果，此时递归结束。</font>
		</p>
		<p>
				<font face="Courier New">在程序中，一定要注意递归的现场保护和恢复，也就是递归调用之前与之后，现场状态应该保持一致。<br />在上述算法中，递归现场就是指数组，2.1.2 改变数组以进行下一层递归调用，<br />2.1.3 则恢复数组，以确保当前递归调用获得下一个正确的排列。</font>
		</p>
		<p>
				<font face="Courier New">括号 () 的作用只是改变运算符的优先级，也就是运算符的计算顺序。<br />所以在以上算法中，无需考虑括号。括号只是在输出时需加以考虑。</font>
		</p>
		<p>
				<br />
				<font face="Courier New">程序中比较重要的地方解释如下： <br /> (1) int Search(int, int) 就是递归函数. char expression[][] 存放每一步产生的表达式，最后的输出中要用到。<br /> expression[][] 与 number[][] 类似，也是递归调用的现场，必须在下一层递归调用前改变、在下一层递归调用后恢复。<br /> <br /> (2) number[][] 数组长度只有4。 在 Search() 中，每次取出两个数后，使用局部变量 a, b 保存这两个数，<br /> 同时数组中加入运算结果，并调整数组使得有效的数字都排列在数组前面。<br /> 在下一层递归调用后，利用局部变量a, b 恢复整个数组。对 expression[][] 的处理与 number[][] 类似。 <br /> <br /> (3) 因为 + * 满足交换率而 - / 不满足，所以程序中，从数组生成两个数的排列， <br /> for (i = 0; i &lt; n; i++) {<br />   for (j = i + 1; j &lt; n; j++) {<br /> 其内层循环 j 是从 i+1 -&gt; n，而非从 0-&gt;n，因为对于交换率来说，两个数字的顺序是无所谓的。<br /> 当然，循环内部对 - / 做了特殊处理，计算了 a-b b-a a/b b/a 四种情况。 <br /> <br /> (4) 此程序只求出第一个解。当求出第一个解时，通过层层 return true 返回并输出结果，然后程序结束。 <br /> <br /> (5) 以 double 来进行求解，定义精度，用以判断是否为 24 。考虑 (5-1/5)*5 这个表达式就知道这么做的原因了。 <br /> <br /> (devil) 输出时，为每个表达式都添加了括号。</font>
		</p>
		<p>
				<font face="Courier New">（6）  输出时，为每个表达式都添加了括号。<br /></font>
		</p>
<img src ="http://www.cppblog.com/yaowf99/aggbug/16623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yaowf99/" target="_blank">Whale</a> 2006-12-19 20:45 <a href="http://www.cppblog.com/yaowf99/articles/16623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>