E18223: 24点
brute force, http://cs101.openjudge.cn/pctbook/E18223/
给定4个整数,判断是否能只用加减运算(即在4个数中间插入3个+或-符号,可以调换数字顺序),使得运算结果为24。
输入
第一行1个整数,代表m组数据(1≤m≤100) 接下来m行,每行为4个整数, Xi (1≤Xi≤10^100),注意整数可能很大。
输出
共m行,每行为YES或者NO,代表是否能凑成24点。 对于如下输入,6+6+6+6=24,25-3+1+1=24,100000000000000000000000-100000000000000000000000-100000000000000000000000+100000000000000000000024=24
样例输入
4
6 6 6 6
3 25 1 1
100000000000000000000000 100000000000000000000000 100000000000000000000000 100000000000000000000024
2 3 4 5样例输出
YES
YES
YES
NO来源:cs101-2018
直接穷举
m = int(input())
for i in range(m):
a,b,c,d = [int(num) for num in input().split()]
flag = False
for j in [a, -a]:
for k in [b, -b]:
for l in [c, -c]:
for m in [d, -d]:
if j + k + l + m == 24:
flag = True
print('YES' if flag else 'NO')example: permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
from itertools import permutations
m = int(input())
mx = [input().split() for _ in range(m)]
def v(i):
a,b,c,d = i
l2 = list(permutations([a,b,c,d], 4))
for j in l2:
a,b,c,d = j
for u in ('+','-'):
for j in ('+','-'):
for k in ('+', '-'):
if eval(a+u+b+j+c+k+d)==24:
return 'YES'
return 'NO'
for i in mx:
print(v(i))2021fall-cs101,黄湘榆,http://cs101.openjudge.cn/practice/18223/
因为不想穷举公式,觉得穷举加减符号应该会比较简洁,所以从网上找到了operator.add和operator.sub。基本思路就是把加减符号的各种排列方式列出来储存在一个字典里,之后再用循环把字典里的每个符号组合都过一遍。之前一直WA是因为for o in output之前的else缩进错误,日后要多注意。
import operator
m =int(input())
op = ["+++", "---", "++-", "+-+", "-++", "+--", "-+-", "--+"]
op_dict ={"+": operator.add, "-": operator.sub}
output = []
for i in range(m):
a,b,c,d = [int(a) for a in input().split()]
for o in op:
if abs( op_dict[o[2]](op_dict[o[1]](op_dict[o[0]](a,b), c), d))==24:
output.append("YES")
break
else:
output.append("NO")
print('\n'.join(output))2021fall-cs101,留美琪
调用permutation进行排列组合,同时使用set是防止数字相同时,出现排列相同情况,重复计算。运算符考虑以下4中:['+++', '++-', '+--', '---'],但是看老师录课的时候,发现枚举了8种情况,但个人感觉以上4种足够了。运算符号的主要区别在于"-"号的个数,因为数字的顺序在改变,以1,2,3,4和"++-"与"+-+"为例,1+2+3-4 =1+2-4+3,因此上述4种应该是囊括了所有情况的。(后来看到微信群里有人仅对运算符号进行排列组合,所以数字和运算符号仅需对其中一种进行组合就可以了)。
# 2021fall-cs101,留美琪
import itertools
m = int(input())
for _ in range(m):
a, b, c, d = map(int, input().split())
res = a + b + c + d
data = set(itertools.permutations([a,b,c,d],4))
for i in data:
res1 = i[0] + i[1] + i[2] - i[3]
res2 = i[0] + i[1] - i[2] - i[3]
res3 = i[0] - i[1] - i[2] - i[3]
if res==24 or res1 == 24 or res2 == 24 or res3==24:
print('YES')
break
else:
print('NO')四个数通过加减运算等价于为每个数分配正负号后求和,其符号组合共 2^4=16 种,构成全部解空间。 本方法采用蒙特卡洛随机采样策略,进行 256 次随机试验,检查目标值 24 是否在结果中出现,以此近似判断解的存在性。
import random
# 读取测试组数
num_tests = int(input())
for _ in range(num_tests):
# 读取四个整数
numbers = list(map(int, input().split()))
# 构建每个数的正负选项 [[a, -a], [b, -b], [c, -c], [d, -d]]
pos_neg_options = []
for num in numbers:
pos_neg_options.append([num, -num])
# 存储随机模拟的结果
simulation_results = []
# 进行 256 次随机模拟
for _ in range(256):
total = 0
# 对每个数,随机选择正或负
for i in range(4):
total += random.choice(pos_neg_options[i])
simulation_results.append(total)
# 判断 24 是否在模拟结果中出现
print('YES' if 24 in simulation_results else 'NO')