【DFS】【DP】【DG特长生2017】T2益智游戏

39 篇文章 0 订阅

题目大意

24点游戏。
给你n组数据,要你得出这四个数是否能完成24点。
需要注意的是可以使用括号且数字顺序可调换,运算过程中只能出现整数。
(然而原题面上没说数字顺序可调换…导致一堆人比赛时70分…)


原题:顺序可调换

由于顺序可以打乱,直接暴力dfs看看能不能合成24。

顺序不可调换

啊啊,挺头裂的。
悄悄跑去问TJH大爷这题怎写。

TJH:我不清楚对不对啊 就暴搜啊
我:这题气得我想用桶…
TJH:这?我用了个vector

好。vector,我不会。再见。

于是写了个DP。分区间处理结果…再合并。然后一个区间可能有多种结果…又再枚举出来、运算。
然后,就五重了…
整挺烦的。


代码

原题:顺序可调换
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int flag,b[11],a[11],t;
void dfs(int now, int z){
	if(now == 4){
		if(z == 24) flag = 1;
		return;
	} 
	for(int i = 1; i <= 4; ++i)
		if(b[i] == 0){
			b[i] = 1;
			dfs(now+1, z+a[i]);  //加减乘除
			dfs(now+1, z-a[i]);
			dfs(now+1, z*a[i]);
			if(a[i] != 0) if(z % a[i] == 0) dfs(now+1, z/a[i]); //除法特别判断
			b[i] = 0;
		}
}
void work(){
	scanf("%d%d%d%d",&a[1], &a[2], &a[3], &a[4]);
	memset(b, 0, sizeof(b));
	flag = 0;
	for(int i = 1; i <= 4; ++i){  //枚举第一个数
		b[i] = 1;
		dfs(1, a[i]);  //正或负
		dfs(1, -a[i]);
		if(flag == 1) break;
		b[i] = 0;
	} 
	if(flag == 1) printf("1\n");
	else printf("0\n");
}
int main(){
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	scanf("%d", &t);  //多组数据
	while(t--) work();
	fclose(stdin);
	fclose(stdout);
} 
顺序不可调换

(注释都不想打了…艹

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int flag, s[10][10][10000], a[10], l[10][10], t;
void work(){
	scanf("%d%d%d%d", &a[1], &a[2], &a[3], &a[4]);
	memset(s, 0, sizeof(s));
	memset(l, 0, sizeof(l));
	l[1][1] = 1; l[2][2] = 1; l[3][3] = 1; l[4][4] = 1;
	s[1][1][1] = a[1];
	s[2][2][1] = a[2];
	s[3][3][1] = a[3];
	s[4][4][1] = a[4];
	for(int len = 2; len <= 4; ++len)  // 长度 
		for(int q = 1; q <= 5-len; ++q) // 起始
			for(int d = q; d < q+len-1; ++d){ //断点:从q到d,从d+1到q+len-1
				for(int jg1 = 1; jg1 <= l[q][d]; ++jg1) //前个区间的可能的结果
					for(int jg2 = 1; jg2 <= l[d+1][q+len-1]; ++jg2){ //后个区间的可能的结果
						s[q][q+len-1][++l[q][q+len-1]] = s[q][d][jg1] + s[d+1][q+len-1][jg2];
						s[q][q+len-1][++l[q][q+len-1]] = s[q][d][jg1] - s[d+1][q+len-1][jg2];
						s[q][q+len-1][++l[q][q+len-1]] = s[q][d][jg1] * s[d+1][q+len-1][jg2];
						if(s[d+1][q+len-1][jg2] != 0) 
						if(s[q][d][jg1] % s[d+1][q+len-1][jg2] == 0)
							s[q][q+len-1][++l[q][q+len-1]] = s[q][d][jg1] / s[d+1][q+len-1][jg2];
					}
			}
	for(int i = 1; i <= l[1][4]; ++i)
		if(s[1][4][i] == 24) {
			printf("1\n");
			return;
		}
	printf("0\n");
}
int main(){
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	scanf("%d", &t);
	while(t--) work();
	fclose(stdin);
	fclose(stdout);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值