问题描述
游戏规则:
从键盘输入任意1-13的4个数,然后用算术运算符“+、一、*、/”将这四个数组成一一个算术表达式(可加括号,每个数字只能使用1次),使得该式的运算结果为24,每输入一次表达式,系统给出该式的运算结果,如果结果是24,则游戏结束;如果不是,则继续组合表达式,直到结果为24为止。
问题分析
本题最简单的解法就是应用穷举法搜索整个解的空间,然后筛选出符合项的全部解,因此关键就是如何确定该题的解题空间。
假设输入4个整数,A,B,C,D,如果只考虑括号不考虑优先级的情况,有一下几种情况:
(1). ((A□B)□C)□D
(2). (A□(B□C))□D
(3). A□(B□(C□D))
(4). A□((B□C)□D)
(5). (A□B)□(C□D)
即在□输入“+、-、*、/”中的任意一种。我们就是在填入的所有式子中所得到的答案里面找出答案为24的表达式。
算法设计
我们在不同的地方设置不同的变量,即:op1、op2、op3,并且规定A和B之间的运算符为op1,B和C之间的运算符为op2,C和D之间的运算符为op3。即:
A op1 B op2 C op3 D
又规定op1、op2、op3的取值范围为1、2、3、4分别为加减乘除,如表所示:
op1、op2、op3变量值 | 表示的运算 |
---|---|
1 | + |
2 | - |
3 | * |
4 | / |
此时就得到了以下算法:
for(op1=1;op1<=4;op1++)
for(op2=1;op2<=4;op2++)
for(op3=1;op3<=4;op3++)
{得到一种不含括号的表达式情形:A op1 B op2 C op3 D
}
下面我们要填入符号,根据括号和优先级的限制,我们有以下的填入方式
(1). ((A+B)-C)×D
(2). (A+(B-C))×D
(3). A+(B-(C×D))
(4). A+((B-C)×D)
(5). (A+B)-(C×D)
根据优先级来说,以上五种情况包括了全部的算式,我们只需计算出每个表达式的值,将其与24进行比较。
float calculate_model1(float i,float j,float k,float t,
int op1,int op2,int op3)
{ /*对应关系式 ((A□B)□C)□D */
float r1,r2,r3;
r1 = cal(i,j,op1);
r2 = cal(r1,k,op2);
r3 = cal(r2,t,op3);
return r3;
}
float calculate_model2(float i,float j,float k,float t,
int op1,int op2,int op3)
{ /*对应关系式 (A□(B□C))□D */
float r1,r2,r3;
r1 = cal(j,k,op2);
r2 = cal(i,r1,op1);
r3 = cal(r2,t,op3);
return r3;
}
float calculate_model3(float i,float j,float k,float t,
int op1,int op2,int op3)
{ /*对应关系式 A□((B□C)□D) */
float r1,r2,r3 ;
r1 = cal(k,t,op3);
r2 = cal(j,r1,op2);
r3 = cal(i,r2,op1);
return r3;
}
float calculate_model4(float i,float j,float k,float t,
int op1,int op2,int op3)
{ /*对应关系式 ((A□B)□C)□D */
float r1,r2,r3;
r1 = cal(j,k,op2);
r2 = cal(r1,t,op3);
r3 = cal(i,r2,op1);
return r3;
}
float calculate_model5(float i,float j,float k,float t,
int op1,int op2,int op3)
{ /*对应关系式 (A+B)-(C×D) */
float r1,r2,r3 ;
r1 = cal(i,j,op1);
r2 = cal(k,t,op3);
r3 = cal(r1,r2,op2);
return r3;
}
上述算法中,每一个函数对应一种表达式类型, 其返回值为表达式的值,原表达式式的形式为i opl j op2 k op3 t
,不同的表达式类型,根据其运算时优先级的不同进行不同的运算。其中函数cal()的作用是通过每种表达式的状态计算出对应的表达式的值。
int op1,op2,op3;
int flag=0;
for(op1=1;op1<=4;op1++)
for(op2=1;op2<=4;op2++)
for(op3=1;op3<=4;op3++)
op1、op2、op3都是取 “+”,“-”,“*”,“/”四个选项
函数cal()包括3个参数,第3个参数为运算符变量,它标志着不同种类的运算符,前两个参数为运算数。该函数的作用是使用前两个参数指定的操作数进行第3个参数指定的运算,并返回其运算结果。例如函数调用cal(2,3.1)的作用是计算2+3=5.并返回5。函数cal0的代码如下:
float cal(float x,float y,int op)
{
switch(op)
{
case 1:return x+y;
case 2:return x-y;
case 3: return x*y;
case 4: return x/y;
}
}
将上面所讲的算法进行结合,可以遍历由4个操作数(范围:1-13), 3个运算符(+,-,*,/),这样就缩小了搜索空间,提高查询效率。
主函数
main()
{
int i,j,k,t;
printf("Please input four integer (1~13)\n");
输入 i,j,k,t四位数。
loop: scanf("%d %d %d %d",&i,&j,&k,&t);
if(i<1||i>13 || j<1||j>13 || k<1||k>13 || t<1||t>13){
printf("Input illege, Please input again\n");
goto loop;
}
如果这四位数小于1或者大于13,则报错。
if(i==j||i==k || i==t||j==k || j==t||k==t){
printf("Input wrong, Please input again\n");
goto loop;
}
如果这四位数有一位以上的数输入了2遍,则报错(题目要求只能用一次)
if(get24(i,j,k,t));
else
{printf("Sorry, the four integer cannot be calculated to get 24\n");
goto loop;}
}
如果这四个数通过运算不等于24,则需要重新输入4位数重新计算
goto loop;表示继续执行不退出。
完整代码
以下是完整代码:
#include<stdio.h>
char op[5]={'#','+','-','*','/',};
float cal(float x,float y,int op)
{
switch(op)
{
case 1:return x+y;
case 2:return x-y;
case 3: return x*y;
case 4: return x/y;
}
}
float calculate_model1(float i,float j,float k,float t,int op1,int op2,int op3)
{
float r1,r2,r3;
r1 = cal(i,j,op1);
r2 = cal(r1,k,op2);
r3 = cal(r2,t,op3);
return r3;
}
float calculate_model2(float i,float j,float k,float t,int op1,int op2,int op3)
{
float r1,r2,r3;
r1 = cal(j,k,op2);
r2 = cal(i,r1,op1);
r3 = cal(r2,t,op3);
return r3;
}
float calculate_model3(float i,float j,float k,float t,int op1,int op2,int op3)
{
float r1,r2,r3 ;
r1 = cal(k,t,op3);
r2 = cal(j,r1,op2);
r3 = cal(i,r2,op1);
return r3;
}
float calculate_model4(float i,float j,float k,float t,int op1,int op2,int op3)
{
float r1,r2,r3;
r1 = cal(j,k,op2);
r2 = cal(r1,t,op3);
r3 = cal(i,r2,op1);
return r3;
}
float calculate_model5(float i,float j,float k,float t,int op1,int op2,int op3)
{
float r1,r2,r3 ;
r1 = cal(i,j,op1);
r2 = cal(k,t,op3);
r3 = cal(r1,r2,op2);
return r3;
}
get24(int i,int j,int k,int t)
{
int op1,op2,op3;
int flag=0;
for(op1=1;op1<=4;op1++)
for(op2=1;op2<=4;op2++)
for(op3=1;op3<=4;op3++)
{
if(calculate_model1(i,j,k,t,op1,op2,op3)==24)
{
printf("((%d%c%d)%c%d)%c%d=24\n",i,op[op1],j,op[op2],k,op[op3],t);
flag = 1;
}
if(calculate_model2(i,j,k,t,op1,op2,op3)==24)
{
printf("(%d%c(%d%c%d))%c%d=24\n",i,op[op1],j,op[op2],k,op[op3],t);
flag = 1;
}
if(calculate_model3(i,j,k,t,op1,op2,op3)==24)
{
printf("%d%c(%d%c(%d%c%d))=24\n",i,op[op1],j,op[op2],k,op[op3],t);
flag = 1;
}
if(calculate_model4(i,j,k,t,op1,op2,op3)==24)
{
printf("%d%c((%d%c%d)%c%d)=24\n",i,op[op1],j,op[op2],k,op[op3],t);
flag = 1;
}
if(calculate_model5(i,j,k,t,op1,op2,op3)==24)
{
printf("(%d%c%d)%c(%d%c%d)=24\n",i,op[op1],j,op[op2],k,op[op3],t);
flag = 1;
}
}
return flag;
}
main()
{
int i,j,k,t;
printf("Please input four integer (1~13)\n");
loop: scanf("%d %d %d %d",&i,&j,&k,&t);
if(i<1||i>13 || j<1||j>13 || k<1||k>13 || t<1||t>13){
printf("Input illege, Please input again\n");
goto loop;
}
if(i==j||i==k || i==t||j==k || j==t||k==t){
printf("Input wrong, Please input again\n");
goto loop;
}
if(get24(i,j,k,t));
else
{printf("Sorry, the four integer cannot be calculated to get 24\n");
goto loop;}
}
此时改程序已经可以成功实现。