C语言24点的算法?

C的代码,越简单越好

  下面是我自己写的一个程序:

  我的解法是把这个问题分解成了两个子问题,首先求出4个数字的无重复全排列,放到一个数组里面,再对没一个排列情况,从头到尾穷举所有的四则运算情况。注意到除法是特殊的,我用x/y表示x除以y,用x|y表示x分之y。注意到,如果穷举的解得到-24的话,只需要把有减法的地方调换一下顺序就可以了,代码如下
  /***********************************************************************************/
  #include<stdio.h>
  #include<stdlib.h>
  #include<math.h>
  #include<string.h>
  int index[4]={0,1,2,3};//used to generate subscription collection
  int sub[4]; //used in p() only
  float f[4]={8.0f,3.0f,3.0f,8.0f};//the 24 point numbers
  float fs[24][4];//all possible permutaions of f
  float tmp[4]; //used for buf
  int g_number=0; //number of permutations
  float RES[4];
  char op[3];
  void p(int idx){//求全排列的函数
  if(idx==4){
  for(int i=0;i<4;++i){tmp[i]=f[sub[i]];}
  for(int g=0;g<g_number;++g){if(memcmp(fs[g],tmp,sizeof(float)*4)==0)return;}
  for(int i=0;i<4;++i){fs[g_number][i]=f[sub[i]];}
  g_number++;
  return;
  }
  for(int i=0;i<4;++i){//make subscription collections
  bool dupflag=false;
  for(int j=0;j<idx;++j){if(sub[j]==i)dupflag=true;}
  if(dupflag==true)continue;
  sub[idx]=index[i];
  p(idx+1);
  }
  }
  void solve(int L){//对某个排列,递归求所有四则运算的结果,找到就退出
  if(L==3){
  if(fabs(fabs(RES[L])-24.0f)<0.01f){
  printf("Found solution,RES=%f,((%d%c%d)%c%d)%c%d\n",RES[L],
  (int)f[0],op[0],
  (int)f[1],op[1],
  (int)f[2],op[2],
  (int)f[3]);
  exit(0);
  }
  return;
  }
  for(int j=0;j<5;++j){//j judges for operators
  if(j==0){RES[L+1]=RES[L]+tmp[L+1];op[L]='+';solve(L+1);}
  if(j==1){RES[L+1]=RES[L]-tmp[L+1];op[L]='-';solve(L+1);}
  if(j==2){RES[L+1]=RES[L]*tmp[L+1];op[L]='*';solve(L+1);}
  if(j==3&&tmp[L+1]!=0)
  {RES[L+1]=RES[L]/tmp[L+1];op[L]='/';solve(L+1);}
  if(j==4&&RES[L+1]!=0)
  {RES[L+1]=tmp[L+1]/RES[L];op[L]='|';solve(L+1);}
  }
  }
  int main(int argc,char* argv[]){//should avoid 0
  f[0]=atoi(argv[1]);
  f[1]=atoi(argv[2]);
  f[2]=atoi(argv[3]);
  f[3]=atoi(argv[4]);
  p(0);
  for(int i=0;i<g_number;++i){
  memcpy(tmp,fs[i],sizeof(float)*4);
  RES[0]=tmp[0];
  for(int t=0;t<4;++t){ printf("%d,",(int)tmp[t]); }
  printf("\n");
  solve(0);
  }
  printf("Found no solution :( \n");
  return 0;
  }

  ----------编译运行,运行时的参数就是4个数字
  g++ p.cpp && ./a.out 1 5 5 5
  1,5,5,5,
  Found solution,RES=-24.000000,((1/5)-5)*5
  g++ p.cpp && ./a.out 8 3 3 8
  8,3,3,8,
  Found solution,RES=-24.000006,((8/3)-3)|8
  上面这个解写出来就是
  8
  --------- = 24
  3-(8/3)
  主程序为了简化,省去了对输入的检查,楼主可以自己添加。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2020-03-31
1:你的函数非要用int
函数名()这样的吗?
2:试试重载fabs()这个,因为fabs默认参数是double型的,你传进去的是float型的,会有精度丢失。
3:这个24点真的很挫。。。。
第2个回答  推荐于2016-01-01
把随机生成的四个数放到数组里,判断加起来等于24就好;
参考代码如下:
#include <stdio.h>
#include <string.h>
#include <math.h>

#define LING 1E-6
#define CONT 4
#define VOLUE 24

float number[CONT];
char expression[CONT][20] ;
bool m_judge = false; //判断是否有解。
int count = 0;

void Find(int n)
{
int i = 0, j = 0;

if (n == 1)
{
if ( fabs(number[0] - 24) <= LING)
{
for (i = 0; i < 20; i++)
{
printf("%c", expression[0][i]) ;
}
printf("\t\t") ;
m_judge = true;
count ++;
if((count % 2)==0) //使输出时每行三个表达式
printf("\n") ;
}
else
{ }
}
for(i = 0; i < n; i++) //查找
{
for (j = i + 1; j < n; j++) //与其后面的查找进行计算
{
float a, b;
char expressiona[20], expressionb[20];
a = number[i] ;
b = number[j] ;
number[j] = number[n - 1];

strcpy(expressiona, expression[i]) ;
strcpy(expressionb, expression[j]) ;
strcpy(expression[j], expression[n - 1]) ;
sprintf(expression[i], "(%s+%s)", expressiona, expressionb) ;
number[i] = a + b;
Find(n-1);
///////////////////////////////////
sprintf(expression[i], "(%s-%s)", expressiona, expressionb) ;
number[i] = a - b;
Find(n-1);
sprintf(expression[i], "(%s-%s)", expressionb, expressiona) ;
number[i] = b - a;
Find(n-1);
sprintf(expression[i], "(%s*%s)", expressiona, expressionb) ;
number[i] = a * b;
Find(n-1);
if (b != 0)
{
sprintf(expression[i], "(%s/%s)", expressiona, expressionb) ;
number[i] = a / b;
Find(n-1);
}
if (a != 0)
{
sprintf(expression[i], "(%s/%s)", expressionb, expressiona) ;
number[i] = b / a;
Find(n-1);
}
number[i] = a; // 最后一层的Find(2)调用完成后将a重新赋值给number[i]即number[0]
number[j] = b; // 最后一层的Find(2)调用完成后将b重新赋值给nubmer[j]即number[1]
strcpy(expression[i], expressiona) ;
strcpy(expression[j], expressionb) ;
}
}
}
int main()
{
int i, j ;
printf("请输入四个数:\n") ;
for (i = 0; i < CONT; i++)
{
char ch[20], s;
int a ;
printf("第%d个数:", i+1) ;
scanf("%f", &number[i]) ;
a = (int)number[i] ;
s = char(a + 48);
ch[0] = s ;
for (j = 1; j < 20; j++)
{
ch[j] = 0 ;
}
strcpy(expression[i], ch) ;
}
printf("\n") ;
Find(CONT) ;
if(m_judge==true)
{
printf("\n\n成功!\n") ;
printf("总共的计算方法共有:%d\n", count) ;
}
else
{
printf("失败!") ;
}
return 0;
}
第3个回答  2010-04-01
#include<stdio.h>
#define C case
double fun(double a1,double a2,int b)
{switch(b)
{C 0:return (a1+a2);
C 1:return (a1-a2);
C 2:return (a1*a2);
C 3:return (a1/a2);
}
}
void main()
{ int g;
for(g=0;g<100;)
{int i,j,k,l,n,m,r,save[4];
double num[4]={1,1,1,1},tem1,tem2,tem3,abc=1111;
char sign[5]="+-*/";
printf("请输入4个数,数字与数字之间用空格隔开:");
for(i=0;i<4;i++)
{scanf("%lf",num+i); save[i]=num[i];}
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(j!=i)
{for(k=0;k<4;k++)
if(k!=i&&k!=j)
{for(l=0;l<4;l++)
if(l!=i&&l!=j&&l!=k)
{for(n=0;n<4;n++)
for(m=0;m<4;m++)
for(r=0;r<4;r++)
{tem1=fun(num[i],num[j],n);
tem2=fun(tem1,num[k],m);
tem3=fun(tem2,num[l],r);
if(tem3==24.0)printf("{(%d%c%d)%c%d}%c%d=24\n",save[i],sign[n],save[j],sign[m],save[k],sign[r],save[l]);
else if(tem3==-24.0)printf("{%d%c(%d%c%d)}%c%d=24\n",save[k],sign[m],save[i],sign[n],save[j],sign[r],save[l]);
else if(tem3==1.0/24.0)printf("%d%c{(%d%c%d)%c%d}=24\n",save[l],sign[r],save[i],sign[n],save[j],sign[m],save[k]);
else if(tem3==-1.0/24.0)printf("%d%c{%d%c(%d%c%d)}=24\n",save[l],sign[r],save[k],sign[n],save[i],sign[m],save[j]);
else
{tem1=fun(num[i],num[j],n);
tem2=fun(num[k],num[l],r);
tem3=fun(tem1,tem2,m);
if(tem3==24.0) printf("(%d%c%d)%c(%d%c%d)=24\n",save[i],sign[n],save[j],sign[m],save[k],sign[r],save[l]);
}
}
}
}
}
g++;
}
}
相似回答