【DG2017特长生】益智游戏

题目描述

给出四个数,判断能否算成24,可以调换顺序,只能加减乘除和括号

样例输入

2
1 2 3 7
1 1 1 1

样例输出

1
0

思路

全排列之后爆搜,然后分组考虑括号的情况
虽然我还是没A
但是是题目的描述有锅,要不然就切了…

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

int b, a[15], ans[4][4][100005], n, num[10][10], rr[12], xx[12], read[12];

int dfs(int l, int r, int x)
{
	if(l == r) ans[l][r][++num[l][r]] = rr[l];
	if(r - l == 1) {
		if(x == 1) ans[l][r][++num[l][r]] = rr[r] + rr[l];
		if(x == 2) ans[l][r][++num[l][r]] = rr[l] - rr[r];
		if(x == 3) ans[l][r][++num[l][r]] = rr[l] * rr[r];
		if(a[r] != 0 && a[l] % a[r] == 0) ans[l][r][++num[l][r]] = rr[l] / rr[r];	
	}//计算分了之后的小区间
	for(int i = l; i <= r; ++i)
	{	
		int sum, sum2;
		if(!num[l][i]) for(int j = 1; j <= 5; ++j) dfs(l, i, j);
		if(!num[i + 1][r]) for(int k = 1; k <= 5; ++k) dfs(i + 1, r, k);
		for(int j = 1; j <= num[l][i]; ++j) {
			sum = ans[l][i][j];
				for(int k = 1; k <= num[i + 1][r]; ++k) {
					sum2 = ans[i + 1][r][k];
					if(x == 1) ans[l][r][++num[l][r]] = sum + sum2;
					if(x == 2) ans[l][r][++num[l][r]] = sum - sum2;
					if(x == 3) ans[l][r][++num[l][r]] = sum * sum2;
					if(sum2 != 0 && sum % sum2 == 0) ans[l][r][++num[l][r]] = sum / sum2;
				}//分别处理
			}
	}
}

void dfss(int now)
{
	if(now > 3) 
	{
		memset(num, 0, sizeof(num));
		memset(ans, 0, sizeof(ans));
		for(int i = 0; i <= 3; ++i)
			rr[xx[i]] = a[i]; 
		for(int j = 1; j <= 4; ++j)
			dfs(0, 3, j);
		for(int j = 1; j <= num[0][3]; ++j)
			if(ans[0][3][j] == 24) {
				printf("1\n");
				b = 1;
				break;
			}
		if(b) return;
	}
	for(int i = 0; i <= 3; ++i)
	{
		if(!read[i]) {
			read[i] = 1;
			xx[now] = i;
			dfss(now + 1);
			if(b) return;
			read[i] = 0;
			xx[now] = 0;
		}
	}//求全排列
}

int main()
{
//	freopen("game.in", "r", stdin);
//	freopen("game.out", "w", stdout);
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i)
	{
		b = 0;
		memset(num, 0, sizeof(num));
		memset(ans, 0, sizeof(ans));
		scanf("%d%d%d%d", &a[0], &a[1], &a[2], &a[3]);
		dfss(0);
		if(!b) printf("0\n");
	}
	return 0;
	fclose(stdin);
	fclose(stdout);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值