/* 解决问题难点: 1:如何列举出所有可能情况。 2:对列举的情况如何解如何表达输出。
/*《一》 问题: 计算24*/
/* 从屏幕1~14中输入四个数字,通过“+,-,*,/,()”构造表达式计算是否存在结果为24的.
/* 存在这样的表达式,就把它输出来且找出所有的请况。
/* 注: 要求(输入数字的顺序输出时不能改变)(运算符可以多次选用)
/*《二》 算法分析:
/* 这是多情况问题,可采用 暴力枚举(穷举法) 把所有的情况枚举出来。如何找多所有的枚举解空间呢?
/* 假设输入的四个数为:A,B,C,D 如果不考虑“()”的情况,仅用运算符连接 则有4*4*4*4=64种表达式
/*
/* 如果不考虑运算符,只考虑"()" 情况,则有五种可能 ((A @ B) @ C) @ D, ( A @( B @ C))@ D,
/* (A @ B )@( C @ D), A @ (B @ (C @ D)), A @(( B @ C )@ D),
/* 故:总共有64 * 5= 320 种可能表达式。也就是说输入四个数以任何运算符、任何优先级运算都包含在这320
/* 表达式中了。
/* 上面的就是运用穷举法 解决本题的基本思想。 下面介绍具体的实现过程。
/* 不同的运算符位置设置成不同的变量:op1,op2,op3 规定为:A op1 B op2 C op3 D
/* op1,op2,op3 取值范围:1 2 3 4 (分别代表:+,-,*,/)
/* 这样就可以得到64中表达式实现:
/* for(op1=1; op1<=4; op1++)
/* for(op2=1; op2<=4; op2++)
/* for(op1=3; op3<=4; op3++)
/* { 得到一种不含括号的表达式 A op1 B op2 C op3 D}*/
/* 下面的问题是如何加入括号:*/
/* 添加括号有五种可能:可一一列举五种情况. 此时就确定了表达式*/
/* 表达是确定后、可另写一个函数计算*/
/* 两个数与一个的计算。 在采用嵌套调用,即可完成一个表达式的计算。*/
/*《三》 算法伪代码: <和上面的实现基本上差不多了>*/
/*《四》 算法实现代码:*/
#include <stdio.h>
//#include <bios.h>
int key;//=0 //x011b;
void print_expression(float *number);/*输入四个数计算24*/
float cal(float x,float y,int op);/*计算两个数*/
void main()
{
float num[4];
while(1)
{
printf("输入4个要计算24的 先按1 键 ,或输入0 结束!/n");
scanf("%d",&key);
if(key==0) break;
for(int count=0; count<4 ;count++)
scanf("%f", &num[count]);
printf("/n");
print_expression(num);
}
}
void print_expression(float *number)
{
char op[6]="0+-*/";/*用于输出表达式*/
key=0;
for(int op1=1; op1<=4; op1++)
for(int op2=1; op2<=4; op2++)
for(int op3=3; op3<=4; op3++)
{
if( cal( cal( cal(number[0],number[1],op1), number[2],op2) , number[3],op3) ==24 )
{
printf("((%3.0f%c%3.0f)%c%3.0f)%c%3.0f = 24/n",number[0],op[op1],number[1],op[op2],number[2],op[op3],number[3]);
key=1;
}
if( cal( cal( number[0],cal(number[1], number[2],op2), op1) , number[3],op3) ==24 )
{
printf("(%3.0f%c(%3.0f%c%3.0f))%c%3.0f = 24/n",number[0],op[op1],number[1],op[op2],number[2],op[op3],number[3]);
key=1;
}
if( cal( cal( number[0],number[1],op1), cal( number[2], number[3],op3) ,op2) ==24 )
{
printf("(%3.0f%c%3.0f)%c(%3.0f%c%3.0f) = 24/n",number[0],op[op1],number[1],op[op2],number[2],op[op3],number[3]);
key=1;
}
if( cal( number[0],cal( cal(number[1], number[2],op2) , number[3],op3), op1) ==24 )
{
printf("%3.0f%c((%3.0f%c%3.0f)%c%3.0f) = 24/n",number[0],op[op1],number[1],op[op2],number[2],op[op3],number[3]);
key=1;
}
if( cal( number[0],cal( number[1], cal( number[2],number[3],op3),op2), op1) ==24 )
{
printf("%3.0f%c(%3.0f%c(%3.0f%c%3.0f)) = 24/n",number[0],op[op1],number[1],op[op2],number[2],op[op3],number[3]);
key=1;
}
}
if(!key)
{
printf("不存在得到24的表达式!/n/n");
}
}
float cal(float x,float y,int op)
{
switch(op)
{ case 1: return x+y; /*op等于1,加法运算*/
case 2: return x-y; /*op等于2,减法运算*/
case 3: return x*y; /*op等于3,乘法运算*/
case 4: return x/y; /*op等于4,除法运算*/
}
}
//《五:新收获》
// 1: 问题条件的复杂时,可以只先考虑问题的部分条件,类举出问题的所有可能解(问题简化法)。就可采用,暴力枚举法。
// 2:解决某些特定表达式可以不用转化成后缀表达式来求解。
//《六:提出设想》
// 当改变条件为: 输入的数据顺序可以在输出时改变呢?( 好似:只用3种表达式就可以了!)。
// 当条件为: 四个运算符只能选择三个不同的时呢?( 则:选三个用排列法列出各种情况!剩下的和上面处理法差不多。)
// 对于上题有什么新的揭发吗?