主题:[讨论]求24点算法
stroyer
[专家分:70] 发布于 2007-03-10 20:56:00
看别人做的24点挺爽的,自己想做,就是不知道算法,哪位高手指点一下.....
回复列表 (共51个回复)
11 楼
stroyer [专家分:70] 发布于 2007-03-10 21:38:00
没看过~~只用过
12 楼
雨中飞燕 [专家分:18980] 发布于 2007-03-10 21:43:00
给个软件来看看嘛,看看它处理的好不好
13 楼
rickone [专家分:15390] 发布于 2007-03-10 21:53:00
我原来想出个非常简单的方法,用VB就可以简单算的;思路也很简单,另外定义两个运算:\ (-)
a\b == b/a
a(-)b == b-a
外加上+-*/共六个运算符。
4个数字排考虑两个二叉树型:
(1) o1
/ \
o2 o3
/ \ / \
n1 n2 n3 n4
(2)
o1
/ \
o2 n1
/ \
o3 n2
/ \
n3 n4
用两个计算函数算这两种情况,循环4个数的无重复全排(24)乘上3个算符的有重复全排(6^3)。
14 楼
stroyer [专家分:70] 发布于 2007-03-10 21:58:00
VB.......
15 楼
stroyer [专家分:70] 发布于 2007-03-10 21:59:00
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define EPS 1e-8
#define DIN double /*或int*/
#define MAX 10 /*或13 */
char strs[12],operator[ ][3]={“+”,“-”,“×”,“÷”};
DIN ans(int iop,DIN x,DIN y)
{ switch(iop)
{ case 1 : return x+y;
case 2 : return x-y;
case 3 : return x*y;
case 4 : if(y)if(sizeof(DIN)==sizeof(int)&&(int)x%(int)y==0
||sizeof(DIN)==sizeof(double))return x/y;
default: return -1; }
}
int ok2(DIN x,DIN y)
{ int ix; for(ix=1; ix<=4; ix++)
if(fabs(ans(ix,x,y)-24)<EPS)return(ix);
return(0);
}
int ok3(DIN a,DIN b,DIN c)
{ int i,j,k; DIN x[3];
x[0]=a; x[1]=b; x[2]=c;
for(i=0; i<3; i++)
for(j=0; j<3; j++)if(j!=i)
for(k=0; k<3; k++)if(k!=i && k!=j)
{ int ix,imid; DIN y;
for(ix=1; ix<=4; ix++)
{ y=ans(ix,x[i],x[j]); if(y<=0)continue;
if((imid=ok2(y,x[k]))!=0)
{ if(i==0)printf(“(%s%s%d)%s%d\n”,strs,operator[ix-1],
(int)x[j],operator[imid-1],(int)x[k]);
else if(j==0)printf(“(%d%s%s)%s%d\n”,(int)x[i],operator[ix-1],
strs,operator[imid-1],(int)x[k]);
else if(k==0)printf(“(%d%s%d)%s%s\n”,(int)x[i],operator[ix-1],
(int)x[j],operator[imid-1],strs);
return(1);
}
}
} return(0);
}
int point24(int p[4])
{ int a,b,c,d,i,ix; DIN y;
for(a=0; a<4; a++)
for(b=0; b<4; b++)if(b!=a)
for(c=0; c<4; c++)if(c!=a && c!=b)
for(d=0; d<4; d++)if(d!=a && d!=b && d!=c)
for(ix=1; ix<=4; ix++)
{ y=ans(ix,p[a],p[b]); if(y<=0)continue;
strs[0]=‘(’; itoa(p[a],&strs[1],10);
strcat(strs,operator[ix-1]); i=strlen(strs);
itoa(p[b], &strs[i],10); i=strlen(strs);
strs[i]=‘)’; strs[i+1]=‘\0’;
if(ok3(y,p[c],p[d]))return(1);
} return(0);
} /* itoa(p[a],&strs[1],10)将p[a]的值按10进制转换成字符串存入&strs[1]*/
main( )
{ int p[4],total,cannot; printf(“4 cards: ”);
scanf(“%d%*c%d%*c%d%*c%d”,p,p+1,p+2,p+3);
point24(p);
/************以下做全面检测********************************************
total=0; cannot=0;
for(p[0]= 1 ; p[0]<=MAX; p[0]++)
for(p[1]=p[0]; p[1]<=MAX; p[1]++)
for(p[2]=p[1]; p[2]<=MAX; p[2]++)
for(p[3]=p[2]; p[3]<=MAX; p[3]++)
{ total++; if(!point24(p)){ cannot++;
printf(“%d,%d,%d,%d\n”,p[0],p[1],p[2],p[3]); }
} printf(“MAX=%d,TOTAL=%d,CANNOT=%d\n”,MAX,total,cannot);
***********************************************************************/
}
16 楼
stroyer [专家分:70] 发布于 2007-03-10 22:03:00
到底有些什么算法~~给点思路撒.....
17 楼
stroyer [专家分:70] 发布于 2007-03-10 22:36:00
请高手赐教哦.....
18 楼
freeeerf [专家分:5440] 发布于 2007-03-10 22:39:00
我写过一个死算的,因为所以情况就只有4的4次方再乘以4的阶.情况不多,再加上有同解的情况,所以算出结果用不了多长时间.
19 楼
rickone [专家分:15390] 发布于 2007-03-10 22:43:00
如果用C,二叉树,我的那个方法可以简化树型,不然还有其它三个,共五个,做遍历没这方便,定义算符,搜索这两棵树,OK了,外写一个输出过程。。。
20 楼
雨中飞燕 [专家分:18980] 发布于 2007-03-11 14:01:00
[quote]我原来想出个非常简单的方法,用VB就可以简单算的;思路也很简单,另外定义两个运算:\ (-)
a\b == b/a
a(-)b == b-a
外加上+-*/共六个运算符。
4个数字排考虑两个二叉树型:
(1) o1
/ \
o2 o3
/ \ / \
n1 n2 n3 n4
(2)
o1
/ \
o2 n1
/ \
o3 n2
/ \
n3 n4
用两个计算函数算这两种情况,循环4个数的无重复全排(24)乘上3个算符的有重复全排(6^3)。[/quote]
偶当初第一次做的时候就是用的这种方法,这种方法需要定义6种运算(就是加减乘除加上反向的减和除)
这个偶早在初二已经用VB实现过,不过在去重复解的能力还不够好,需要写大量的代码--
我来回复