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

2024-11-22 16:37:36
推荐回答(1个)
回答1:

这道题目如果没其他较好的办法就采用暴力穷举解决。根据给定的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( );
}
}