7-2 用扑克牌计算24点 (30 分)

一副扑克牌的每张牌表示一个数(J、Q、K 分别表示 11、12、13,两个司令都表示 6)。任取4 张牌,即得到 4 个 1~13 的数,请添加运算符(规定为加+ 减- 乘* 除/ 四种)使之成为一个运算式。每个数只能参与一次运算,4 个数顺序可以任意组合,4 个运算符任意取 3 个且可以重复取。运算遵从一定优先级别,可加括号控制,最终使运算结果为 24。请输出一种解决方案的表达式,用括号表示运算优先。如果没有一种解决方案,则输出 -1 表示无解。

输入格式:

输入在一行中给出 4 个整数,每个整数取值在 [1, 13]。

输出格式:

输出任一种解决方案的表达式,用括号表示运算优先。如果没有解决方案,请输出 -1。

输入样例:

2 3 12 12

输出样例:

((3-2)*12)+12

 首先,要说的是,对于C语言初学者来说这道题是有一定的难度的,博主作为初学者在期中考试的时候遇到这道题也挂掉了(伤心往事),但对于初学者来说我觉得这道题值得一写,如果在看懂思路和代码之后不查资料靠自己写下来,一定会很有收获。

OK,让我们来讲讲这道题的思路。(其实就是暴力枚举……)

总的来说,因为数据不大,所以我们要做的就是枚举出所有情况然后交给计算机一一检验。那么怎么开始呢?我想会成为很多人的难点。

我们可以看到最后的答案,就是四个数字,三个符号,还有很多括号,是不是有了不一样的想法。没错,我们发现按照数字之间结合的优先顺序,我们可以分为五种情况:                                        (num1,num2等代表数字,op1,op2等代表符号)                                        

(num1 op1 num2) op2 (num3 op3 num4)

((num1 op1 num2) op2 num3) op3 num4   

(num1 op1 (num2 op2 num3)) op3 num4

 num1 op1 ((num2 op2 num3) op3 num4)          

  num1 op1 (num2 op2 (num3 op3 num4))                                                                     

再加上四个数字的全排列和三个位置的符号枚举,我们便可以得到所有的情况。

首先是全排列,我采用的是dfs的经典做法,不过完全没有必要,可以自己写之后存到一个二维数组之中,第一维表示全排列种数,第二维存放排列(即四个数字)

然后是使用三重循环,对三个符号位进行枚举,再用islegal()函数判断该方法是否成立,如果成立按照格式输出即可

详细代码如下

#pragma warning(disable:4996)
#include<stdio.h>
#include<stdlib.h>
double a[24][4];
int flag[5];
double temp[4];
int cnt;
int flag_s;
char op[4] = { '+', '-', '*', '/' };
double b[4];

double cal(double x1, double x2, int op1) {
	double outcome = 0;
	switch (op[op1]) {
	case '+': outcome = x1 + x2; break;
	case '-': outcome = x1 - x2; break;
	case '*': outcome = x1 * x2; break;
	case '/': {
		if (x2 == 0) outcome = -1;
		else outcome = x1 / x2;
		break;
		}
	}
	return outcome;
}

int islegal(int op1, int op2, int op3, double a[][4]) {
	double sum1 = 0, sum2 = 0, sum3 = 0;
	int flag = 0; 
	for (int i = 0; i < 24; i++) {//枚举排列mi9
		sum1 = cal(a[i][0], a[i][1], op1);
		sum2 = cal(a[i][2], a[i][3], op3);
		sum3 = cal(sum1, sum2, op2);
		if(sum3 == 24 ){
			flag = 1;
			printf("(%.0lf%c%.0lf)%c(%.0lf%c%.0lf)\n", a[i][0], op[op1], a[i][1], op[op2], a[i][2], op[op3], a[i][3]);
			break;
		}

		sum1 = cal(a[i][0], a[i][1], op1);
		sum2 = cal(sum1, a[i][2], op2);
		sum3 = cal(sum2, a[i][3], op3);
		if (sum3 == 24) {
			flag = 1;
			printf("((%.0lf%c%.0lf)%c%.0lf)%c%.0lf\n", a[i][0], op[op1], a[i][1], op[op2], a[i][2], op[op3], a[i][3]);
			break;
		}

		sum1 = cal(a[i][1], a[i][2], op2);
		sum2 = cal(a[i][0], sum1, op1);
		sum3 = cal(a[i][3], sum2, op3);
		if (sum3 == 24) {
			flag = 1;
			printf("(%.0lf%c(%.0lf%c%.0lf))%c%.0lf\n", a[i][0], op[op1], a[i][1], op[op2], a[i][2], op[op3], a[i][3]);
			break;
		}

		sum1 = cal(a[i][2], a[i][3], op3);
		sum2 = cal(a[i][1], sum1, op2);
		sum3 = cal(a[i][0], sum2, op1);
		if (sum3 == 24) {
			flag = 1;
			printf("%.0lf%c((%.0lf%c(%.0lf%c%.0lf)\n", a[i][0], op[op1], a[i][1], op[op2], a[i][2], op[op3], a[i][3]);
			break;
		}

		sum1 = cal(a[i][1], a[i][2], op2);
		sum2 = cal(sum1, a[i][3], op3);
		sum3 = cal(a[i][0], sum2, op1);
		if (sum3 == 24) {
			flag = 1;
			printf("%.0lf%c((%.0lf%c%.0lf)%c%.0lf)\n", a[i][0], op[op1], a[i][1], op[op2], a[i][2], op[op3], a[i][3]);
			break;
		}
	}
	return flag;
}

void Aqueue(int k) {
	if (k == 4) {
		for (int i = 0; i < 4; i++)
			a[cnt][i] = temp[i];
		cnt++;
	}
	for (int i = 0; i < 4; i++) {
		if (!flag[i]) {
			temp[k] = b[i];
			flag[i] = 1;
			Aqueue(k + 1);
			flag[i] = 0;
		}
	}
}

int main() {
	for (int i = 0; i < 4; i++)
		scanf("%lf", &b[i]);
	Aqueue(0);//已经找了k个数
	//for (int i = 0; i < 24; i++) {
	//	for (int j = 0; j < 4; j++){
	//		printf("%d ", a[i][j]);
	//	if (j == 3) printf("\n");
	//	}
	//}
	for (int i = 0; i < 4; i++) { //枚举符号组合
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				if (islegal(i, j, k, a)) {
					flag_s = 1;
				}
			}
		}
	}

	if (flag_s == 0) printf("-1");
	return 0;
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
扑克牌24点游戏是一种玩法类似于上面提到的数学游戏的游戏。以下是一个C语言实现,可以用扑克牌进行游戏: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> int check(double a, double b, double c, double d) { double exp[5]; int i, j, k, l, m; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (j == i) continue; for (k = 0; k < 4; k++) { if (k == i || k == j) continue; for (l = 0; l < 4; l++) { if (l == i || l == j || l == k) continue; exp[0] = a; exp[1] = b; exp[2] = c; exp[3] = d; for (m = 0; m < 5; m++) { if (m == 0) exp[m] = exp[i] + exp[j]; else if (m == 1) exp[m] = exp[i] - exp[j]; else if (m == 2) exp[m] = exp[i] * exp[j]; else if (m == 3 && exp[j] != 0) exp[m] = exp[i] / exp[j]; else continue; exp[i] = exp[k]; exp[j] = exp[l]; exp[k] = exp[m]; if (k > l) { int temp = k; k = l; l = temp; } exp[l] = exp[3]; if (exp[2] == 24) return 1; } } } } } return 0; } int main() { int i, j, k, l; double a, b, c, d; srand(time(NULL)); while (1) { i = rand() % 13 + 1; j = rand() % 13 + 1; k = rand() % 13 + 1; l = rand() % 13 + 1; if (check(i, j, k, l)) { printf("找到了一组可以得到24的扑克牌:"); if (i == 1) printf("A "); else if (i == 11) printf("J "); else if (i == 12) printf("Q "); else if (i == 13) printf("K "); else printf("%d ", i); if (j == 1) printf("A "); else if (j == 11) printf("J "); else if (j == 12) printf("Q "); else if (j == 13) printf("K "); else printf("%d ", j); if (k == 1) printf("A "); else if (k == 11) printf("J "); else if (k == 12) printf("Q "); else if (k == 13) printf("K "); else printf("%d ", k); if (l == 1) printf("A "); else if (l == 11) printf("J "); else if (l == 12) printf("Q "); else if (l == 13) printf("K "); else printf("%d ", l); printf("\n"); break; } } return 0; } ``` 这个程序中,使用了和上面类似的`check`函数来判断给定的四张扑克牌是否可以得到24。程序使用了`rand()`函数来生成四张随机的扑克牌,如果可以得到24,则输出这四张牌的面值。如果不行,则继续生成新的组合,直到找到一组可以得到24的牌为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值