hdu 1427速算24点(枚举全排列)



题意: 算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数

e鸣杯碰到过这道题,当时手算没算出来现在算报了一箭之仇了吧蛤蛤。但是不一样的是这道题运算过程中不会出现小数,有一个坑是当输入是10的时候其实我只读了1,这也是一开始老wa的原因。

这道题直接暴力有点不和谐,所以可以用next_permutation()来做,总结一下,其实所有运算都可以归结为两类,一类是((a@b)@c)@d 另一类是 (a@b)@(c@d)因为只有四个数,所以这么做没问题,但当操作数增多的时候就有点麻烦了,这时候可以考虑递归来做

代码如下:

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
using namespace std;  
#define LL long long  

const int INF = 100000000;

int a[6];

int sol_input(char ch) {
	if(ch == 'A') return 1;  
    else if(ch == 'J') return 11;  
    else if(ch == 'Q') return 12;  
    else if(ch == 'K') return 13;
    else if(ch == '1') return 10;
    else return ch - '0';
}

int oper(int i, int m, int n) {       //枚举四种运算符 
	if(i == 1) return m + n;
	if(i == 2) return m - n;
	if(i == 3) return m * n;
	if(n == 0 || m % n != 0) return INF;
	else return m / n;
}

bool calcu1(int i, int j, int k) {   //计算顺序1 ((a@b)@c)@d 
	int tmp1 = oper(i, a[0], a[1]);
	int tmp2 = oper(j, tmp1, a[2]);
	int tmp3 = oper(k, tmp2, a[3]);
	if(tmp3 == 24 || tmp3 == -24) return true;
	return false; 
}

bool calcu2(int i, int j, int k) {   //计算顺序2 (a@b)@(c@d) 
	int tmp1 = oper(i, a[0], a[1]);
	int tmp2 = oper(k, a[2], a[3]);
	int tmp3 = oper(j, tmp1, tmp2);
	if(tmp3 == 24 || tmp3 == -24) return true;
	return false;
}

int main() {
	char s[2];
	while(scanf("%s", s) != EOF) {
		a[0] = sol_input(s[0]);
		for(int i = 1; i <= 3; i++) {
			scanf("%s", s);
			a[i] = sol_input(s[0]);
		}
		
		int flag = 0;
		sort(a, a+4);
		do {
			for(int i = 1; i <= 4; i++)
				for(int j = 1; j <= 4; j++)
					for(int k = 1; k <= 4; k++) {
						if(calcu1(i, j, k) || calcu2(i, j, k)) flag = 1;
					}
		} while(next_permutation(a, a+4) && !flag);
		
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值