精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>算法集锦--------梦入玄机>>算24游戏的算法讨论>>老山羊的算24程序

主题:老山羊的算24程序
发信人: yangcs()
整理人: yangcs(2000-03-08 18:37:40), 站内信件
方法一:
# include <stdio.h>
# include <math.h>
# define EPS 0.001
//  出现0或负数就不必再往下算了
float f1(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retur
n x+y; }
float f2(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x-y; }
float f3(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x*y; }
float f4(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x/y; }

void main()
{
int a,b,c,d,i,j,k,m,n,f24;
char s[10000][40]; // 其实s[1000][40]就够了,用来存算24的方法
char fh[4]; // fh[0]='+'; fh[1]='-'; fh[2]='*'; fh[3]='/';
float x[4]; // 用实数记录三张扑克,其实用4个实型变量即可
float (*(p[4]))(float,float); //四个函数指针,用来做四种运算
int flag[10000]; /* 1到10四个数顺序共10000种组合 */

fh[0]='+'; fh[1]='-'; fh[2]='*'; fh[3]='/';
for(a=0;a<10000;a++)
flag[a]=0; /* 初值,不能算24的 */
p[0]=f1;p[1]=f2;p[2]=f3;p[3]=f4;

// 为了编程方便起见,我让四张扑克a,b,c,d都从1循环到10,循环10000次
for(m=n=a=0;a<10;a++)
for(b=0;b<10;b++)
for(c=0;c<10;c++)
for(d=0;d<10;d++,n++)
{
// printf("%d %d %d %d %d\n",a,b,c,d,n);
if(flag[n]) continue;
x[0]=(float) (a+1);x[1]=(float) (b+1);
x[2]=(float) (c+1);x[3]=(float) (d+1);
f24=1;
// i,j,k循环,填写三个符号,共4*4*4次
for(i=0;(i<4)&&f24;i++)
for(j=0;(j<4)&&f24;j++)
for(k=0;(k<4)&&f24;k++)
{
// 括号共有五种组合
if(fabs(p[k](p[j](p[i](x[0],x[1]),x[2]),x[3])-24)<EPS)
{
sprintf(s[m],"A ((%d%c%d)%c%d)%c%d",a+1,fh[i],b+1,fh[j],c+1,fh[k],
d+1);
f24=0;break;
}
if(fabs(p[j](p[i](x[0],x[1]),p[k](x[2],x[3]))-24)<EPS)
{
sprintf(s[m],"B (%d%c%d)%c(%d%c%d)",a+1,fh[i],b+1,fh[j],c+1,fh[k],
d+1);
f24=0;break;
}
if(fabs(p[k](p[i](x[0],p[j](x[1],x[2])),x[3])-24)<EPS)
{
sprintf(s[m],"C (%d%c(%d%c%d))%c%d",a+1,fh[i],b+1,fh[j],c+1,fh[k],
d+1);
f24=0;break;
}
if(fabs(p[i](x[0],p[k](p[j](x[1],x[2]),x[3]))-24)<EPS)
{
sprintf(s[m],"D %d%c((%d%c%d)%c%d)",a+1,fh[i],b+1,fh[j],c+1,fh[k],
d+1);
f24=0;break;
}
if(fabs(p[i](x[0],p[j](x[1],p[k](x[2],x[3])))-24)<EPS)
{
sprintf(s[m],"E %d%c(%d%c(%d%c%d))",a+1,fh[i],b+1,fh[j],c+1,fh[k],
d+1);
f24=0;break;
}
}
// a,b,c,d有一种组合能算出24,则它的任何一种排列都能用同样方法算24。

// 这24种排列方法我就不重新写程序了,我直接赋值
// 全排列程序在精华区里有,阿豪和我的程序最快
if(!f24)
{
//printf("%4d:%s\n",m,s[m]);
m++;
// 下列赋值语句是我把全排列程序稍加改动生成的
// 阿蓉说的没错,全排列程序确实在很多场合下用得到
flag[a*1000+b*100+c*10+d]=m;
flag[b*1000+a*100+c*10+d]=m;
flag[a*1000+c*100+b*10+d]=m;
flag[c*1000+a*100+b*10+d]=m;
flag[b*1000+c*100+a*10+d]=m;
flag[c*1000+b*100+a*10+d]=m;
flag[a*1000+b*100+d*10+c]=m;
flag[b*1000+a*100+d*10+c]=m;
flag[a*1000+d*100+b*10+c]=m;
flag[d*1000+a*100+b*10+c]=m;
flag[b*1000+d*100+a*10+c]=m;
flag[d*1000+b*100+a*10+c]=m;
flag[a*1000+c*100+d*10+b]=m;
flag[c*1000+a*100+d*10+b]=m;
flag[a*1000+d*100+c*10+b]=m;
flag[d*1000+a*100+c*10+b]=m;
flag[c*1000+d*100+a*10+b]=m;
flag[d*1000+c*100+a*10+b]=m;
flag[b*1000+c*100+d*10+a]=m;
flag[c*1000+b*100+d*10+a]=m;
flag[b*1000+d*100+c*10+a]=m;
flag[d*1000+b*100+c*10+a]=m;
flag[c*1000+d*100+b*10+a]=m;
flag[d*1000+c*100+b*10+a]=m;
}
}
// 以上循环如果不考虑中途退出(如果想把所有算24的方法列出),
// 共要循环10*10*10*10*4*4*4*5 = 3,200,000次,
// 实际运算次数远远小于这个数。
// 当然,这种方法重复计算很多,但实际运行时间为1秒钟左右,
// 我就不必计较算法的快慢,只计较程序的可读性了。




// 四张扑克从小到大排列,共有下列种情况能算出24
for(a=0;a<10;a++)
for(b=a;b<10;b++)
for(c=b;c<10;c++)
for(d=c;d<10;d++)
{
n=a*1000+b*100+c*10+d;
if(flag[n])
printf("%2d %2d %2d %2d: %s\n",a+1,b+1,c+1,d+1,s[flag[n]-1]);
}

// 另一种输出方式,可以算出任意抽取四张扑克,能算出24的概率
for(m=a=0;a<10;a++)
for(b=0;b<10;b++)
for(c=0;c<10;c++)
for(d=0;d<10;d++)
{
n=a*1000+b*100+c*10+d;
if(flag[n])
printf("%4d:%2d %2d %2d %2d: %s\n",++m,a+1,b+1,c+1,d+1,s[flag[n
]-1]);
}
}



方法二:

# include <stdio.h>
# include <math.h>
# define EPS 0.001
//  出现0或负数就不必再往下算了
float f1(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retur
n x+y; }
float f2(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x-y; }
float f3(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x*y; }
float f4(float x,float y) { if ((x<EPS)||(y<EPS)) return 0; else retu
rn x/y; }
int func(float,float,float,float);
int a,b,c,d,i,j,k,m,n,f24;
char fh[4]; // fh[0]='+'; fh[1]='-'; fh[2]='*'; fh[3]='/';
float x0,x1,x2,x3; // 用实数记录三张扑克
float (*(p[4]))(float,float); //四个函数指针,用来做四种运算
void main()
{
fh[0]='+'; fh[1]='-'; fh[2]='*'; fh[3]='/';
p[0]=f1;p[1]=f2;p[2]=f3;p[3]=f4;

for(m=n=a=0;a<10;a++)
for(b=a;b<10;b++)
for(c=b;c<10;c++)
for(d=c;d<10;d++,n++)
{
x0=(float) (a+1);x1=(float) (b+1);
x2=(float) (c+1);x3=(float) (d+1);
f24=1;
for(i=0;(i<4)&&f24;i++)
for(j=0;(j<4)&&f24;j++)
for(k=0;(k<4)&&f24;k++)
{
if(!(f24=func(x0,x1,x2,x3))) break;
if(!(f24=func(x1,x0,x2,x3))) break;
if(!(f24=func(x0,x2,x1,x3))) break;
if(!(f24=func(x2,x0,x1,x3))) break;
if(!(f24=func(x1,x2,x0,x3))) break;
if(!(f24=func(x2,x1,x0,x3))) break;
if(!(f24=func(x0,x1,x3,x2))) break;
if(!(f24=func(x1,x0,x3,x2))) break;
if(!(f24=func(x0,x3,x1,x2))) break;
if(!(f24=func(x3,x0,x1,x2))) break;
if(!(f24=func(x1,x3,x0,x2))) break;
if(!(f24=func(x3,x1,x0,x2))) break;
if(!(f24=func(x0,x2,x3,x1))) break;
if(!(f24=func(x2,x0,x3,x1))) break;
if(!(f24=func(x0,x3,x2,x1))) break;
if(!(f24=func(x3,x0,x2,x1))) break;
if(!(f24=func(x2,x3,x0,x1))) break;
if(!(f24=func(x3,x2,x0,x1))) break;
if(!(f24=func(x1,x2,x3,x0))) break;
if(!(f24=func(x2,x1,x3,x0))) break;
if(!(f24=func(x1,x3,x2,x0))) break;
if(!(f24=func(x3,x1,x2,x0))) break;
if(!(f24=func(x2,x3,x1,x0))) break;
if(!(f24=func(x3,x2,x1,x0))) break;
}
if(!f24) m++;
}
printf("m=%d n=%d\n",m,n);
}

int func(float x0,float x1,float x2,float x3)
{
if(fabs(p[k](p[j](p[i](x0,x1),x2),x3)-24)<EPS)
{
printf("A ((%d%c%d)%c%d)%c%d\n",a+1,fh[i],b+1,fh[j],c+1,fh[k],d+1)
;
return 0;
}
if(fabs(p[j](p[i](x0,x1),p[k](x2,x3))-24)<EPS)
{
printf("B (%d%c%d)%c(%d%c%d)\n",a+1,fh[i],b+1,fh[j],c+1,fh[k],d+1)
;
return 0;
}
if(fabs(p[k](p[i](x0,p[j](x1,x2)),x3)-24)<EPS)
{
printf("C (%d%c(%d%c%d))%c%d\n",a+1,fh[i],b+1,fh[j],c+1,fh[k],d+1)
;
return 0;
}
if(fabs(p[i](x0,p[k](p[j](x1,x2),x3))-24)<EPS)
{
printf("D %d%c((%d%c%d)%c%d)\n",a+1,fh[i],b+1,fh[j],c+1,fh[k],d+1)
;
return 0;
}
if(fabs(p[i](x0,p[j](x1,p[k](x2,x3)))-24)<EPS)
{
printf("E %d%c(%d%c(%d%c%d))\n",a+1,fh[i],b+1,fh[j],c+1,fh[k],d+1)
;
return 0;
}
return 1;
}


方法三:主程序同方法二,func()的函数内容:

int func(float x0,float x1,float x2,float x3)
{
// 列出所有情况,……
}

这段程序将会很长,但可以先编写另一段程序生成这段程序,这种方法在实

编程中经常使用。

--
欢迎来到DOS版。那里有一只老羊和一条小狼和sle。
[email protected]

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.72.45.132]

[关闭][返回]