作业帮 > 综合 > 作业

关于24点的C语言代码,能直接使用的,注释最好多一点,以便理解

来源:学生作业帮 编辑:搜搜考试网作业帮 分类:综合作业 时间:2024/06/16 19:20:31
关于24点的C语言代码,能直接使用的,注释最好多一点,以便理解
(1) 4张牌均为1-10内的数(随机产生);
(2)
(3) 必要时可以给出一个提示答案.答案格式例子:2+7=9;9*3=27; 27-3=24
关于24点的C语言代码,能直接使用的,注释最好多一点,以便理解
这道题目如果没其他较好的办法就采用暴力穷举解决.根据给定的4个数,得出两棵不同构的语法树.
O O
/ \ / \
O O 和 o O
/ \ / \ / \
o o o o o O
/ \
o o
分别得出的逆波兰式为:ooOooOO和ooooOOO,其中o为操作数,O为运算符.然后对这两种形式的逆波兰式进行穷举并计算即可.对于第一种逆波兰式共有4!*4^3=4*3*2*4*4*4=1536种不同情况,第二种逆波兰式也有1536种不同情况.因此,若无解,则共循环测试3072次.
include
#include
#include
#include
char RPN[7];
char operdata[24][4] = {{0,1,2,3},{0,1,3,2},{0,2,1,3},{0,2,3,1},{0,3,1,2},{0,3,2,1},/*操作数的24种不同排列*/
{1,0,2,3},{1,0,3,2},{1,2,0,3},{1,2,3,0},{1,3,0,2},{1,3,2,0},
{2,1,0,3},{2,1,3,0},{2,0,1,3},{2,0,3,1},{2,3,1,0},{2,3,0,1},
{3,1,2,0},{3,1,0,2},{3,2,1,0},{3,2,0,1},{3,0,1,2},{3,0,2,1}
};
char oper[64][3]={{-1,-1,-1},{-1,-1,-2},{-1,-1,-3},{-1,-1,-4},/*操作符的64种不同排列*/
{-1,-2,-1},{-1,-2,-2},{-1,-2,-3},{-1,-2,-4}, /*-1~-4分别表示:+ - * / */
{-1,-3,-1},{-1,-3,-2},{-1,-3,-3},{-1,-3,-4},
{-1,-4,-1},{-1,-4,-2},{-1,-4,-3},{-1,-4,-4},
{-2,-1,-1},{-2,-1,-2},{-2,-1,-3},{-2,-1,-4},
{-2,-2,-1},{-2,-2,-2},{-2,-2,-3},{-2,-2,-4},
{-2,-3,-1},{-2,-3,-2},{-2,-3,-3},{-2,-3,-4},
{-2,-4,-1},{-2,-4,-2},{-2,-4,-3},{-2,-4,-4},
{-3,-1,-1},{-3,-1,-2},{-3,-1,-3},{-3,-1,-4},
{-3,-2,-1},{-3,-2,-2},{-3,-2,-3},{-3,-2,-4},
{-3,-3,-1},{-3,-3,-2},{-3,-3,-3},{-3,-3,-4},
{-3,-4,-1},{-3,-4,-2},{-3,-4,-3},{-3,-4,-4},
{-4,-1,-1},{-4,-1,-2},{-4,-1,-3},{-4,-1,-4},
{-4,-2,-1},{-4,-2,-2},{-4,-2,-3},{-4,-2,-4},
{-4,-3,-1},{-4,-3,-2},{-4,-3,-3},{-4,-3,-4},
{-4,-4,-1},{-4,-4,-2},{-4,-4,-3},{-4,-4,-4}
};
void Swap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
int compute(char *a) //如果是一个解,则返回1,否则返回0,a是一个逆波兰式
{
int stack[10], top = -1, i, s1, s2;
for(i = 0; i < 7; i++)
{
if(a[i] > 0 && a[i] < 11) stack[++top] = a[i];
else {
s1 = stack[top--];
s2 = stack[top--];
if(s1 < s2) Swap(s1, s2);
switch(a[i]) {
case -1: stack[++top] = s1 + s2;
break;
case -2: stack[++top] = s1 - s2;
break;
case -3: stack[++top] = s1 * s2;
break;
case -4: if((s1 && s2) && (s1 % s2 == 0)) stack[++top] = s1 / s2;
else return 0;
}
}
}
return (stack[top] == 24);
}
void cout(char *a)
{
int stack[10], top = -1, i, s1, s2;
for(i = 0; i < 7; i++)
{
if(a[i] > 0 && a[i] < 11) stack[++top] = a[i];
else {
s1 = stack[top--];
s2 = stack[top--];
if(s1 < s2) Swap(s1, s2);
switch(a[i]) {
case -1: stack[++top] = s1 + s2;
printf("%d + %d = %d\t", s1, s2, s1+s2);
break;
case -2: stack[++top] = s1 - s2;
printf("%d - %d = %d\t", s1, s2, s1-s2);
break;
case -3: stack[++top] = s1 * s2;
printf("%d * %d = %d\t", s1, s2, s1*s2);
break;
case -4: if(s1 % s2 == 0) stack[++top] = s1 / s2;
printf("%d / %d = %d\t", s1, s2, s1/s2);
}
}
}
}
void main( )
{
char data[4], i, j, k, ch;
int flag;
srand(time(0));
printf("若退出,请按\'n\'键,否则请按其他键继续\n");
ch = getch( );
while(ch != 'n')
{
flag = 0;
for(i = 0; i < 4; i++)
{
data[i] = rand( ) % 10 + 1;
printf("%d ", data[i]);
}
printf("\n");
for(i = 0; i < 24 && !flag; i++)
{
RPN[0] = data[operdata[i][0]];
RPN[1] = data[operdata[i][1]];
RPN[3] = data[operdata[i][2]];
RPN[4] = data[operdata[i][3]];
for(j = 0; j < 64 && !flag; j++)
{
RPN[2] = oper[j][0];
RPN[5] = oper[j][1];
RPN[6] = oper[j][2];

flag = compute(RPN);
if(flag)
{
cout(RPN);
}
}
RPN[0] = data[operdata[i][0]];
RPN[1] = data[operdata[i][1]];
RPN[2] = data[operdata[i][2]];
RPN[3] = data[operdata[i][3]];
for(j = 0; j < 64 && !flag; j++)
{
RPN[4] = oper[j][0];
RPN[5] = oper[j][1];
RPN[6] = oper[j][2];

flag = compute(RPN);
if(flag)
{
cout(RPN);
}
}
}
if(!flag) printf("无解\n");
printf("若退出,请按\'n\'键,否则请按其他键继续\n");
ch = getch( );
}
}
再问: 能不能在代码里面写些注释啊,很多语句不太理解诶,谢谢啦
再答: 对于逆波兰式的分析,是根据上面的两棵不同构的语法树而来,而由语法树得到其对应的逆波兰式是对语法树进行后序遍历而得到的。因此两个不同构的语法树就可得到两种不同构的逆波兰式。而每种逆波兰式,根据操作数的不同排列和操作符的不同组合,又可得到1536个的逆波兰式(存在少部分是相同的)。 char RPN[7];用于存放一个逆波兰式,这里选取用char数组,是因为每个操作数都