首页 > 试题广场 >

24点游戏算法

[编程题]24点游戏算法
  • 热度指数:150410 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}对于给定的四个小于 10 的正整数,你需要计算它们能否通过计算得到数字 24。让我们来回忆标准二十四点游戏的规则:
\hspace{23pt}\bullet\,输入的数字可能会重复,每一个数字必须用且只能用一次;
\hspace{23pt}\bullet\,运算顺序可以任意安排,且可以使用括号进一步地改变运算优先级;
\hspace{23pt}\bullet\,允许使用加、减、乘、除四种算数运算符,其中除法是实数除法;
\hspace{15pt}如果可以得到 24,输出 \rm true,否则,直接输出 \rm false

输入描述:
\hspace{15pt}在一行上输入四个整数 a,b,c,d \left(1 \leqq a,b,c,d \leqq 10\right) 代表等待计算的数字。


输出描述:
\hspace{15pt}如果可以通过规定的计算得到 24,输出 \rm true,否则,直接输出 \rm false
示例1

输入

7 2 1 10

输出

true

说明

\hspace{15pt}在这个样例中,7 \times 1 \times 2 + 10 = 24,因此输出 \rm true
示例2

输入

2 2 2 9

输出

true

说明

\hspace{15pt}在这个样例中,2 + 2 \times (2 + 9) = 24,因此输出 \rm true
示例3

输入

10 9 6 9

输出

true

说明

\hspace{15pt}在这个样例中,10 \times 9 \div 6 + 9 = 24,因此输出 \rm true
示例4

输入

3 3 8 8

输出

true

说明

\hspace{15pt}在这个样例中,8 \div (3 - 8 \div 3) = 24,因此输出 \rm true
示例5

输入

1 1 1 1

输出

false

备注:
\hspace{15pt}本题数据已进行加强(2025/01/09)。
只允许使用加减乘除,结果后面冒出了个要用平方根的算法

发表于 2025-02-22 09:06:48 回复(0)
dig=list(map(int,input().split()))
def dfs(l):
    if len(l)==1:
        return abs(l[0]-24)<1e-6
    for i in range(len(l)):
        for j in range(len(l)):
            if i!=j:
                a=l[i]
                b=l[j]
                l1=[l[k] for k in range(len(l)) if k!=i and k!=j]
                if dfs(l1+[a+b]) or dfs(l1+[a-b]) or dfs(l1+[a*b]) or (b!=0 and dfs(l1+[a/b])):
                    return True
if dfs(dig):
    print('true')
else:
    print('false')
发表于 2025-02-09 00:50:03 回复(0)
如果机试不给出错的测试用例我是万万想不到corner case的…参考了评论区各位大佬的思路,考虑两两组合,以及1555这种需要用括号破坏原有四则运算优先级的
n = input().split()
import itertools
p = itertools.permutations(n)
chrs = ['+', '-', '*', '/']
flag = False
for q in p:
    for i in chrs:
        for j in chrs:
            for k in chrs:
                tmp1 = eval(q[0] + i + q[1])
                tmp2 = eval(str(tmp1) + j + q[2])
                tmp3 = eval(str(tmp2) + k + q[3])
                tmp4 = eval(q[2] + j+ q[3])
                tmp6 = eval((q[0] + j + q[1] + k+ q[2])+ i+q[3])
                if tmp4 == 0 and k == '/':
                    continue
                else:
                    tmp5 = eval(str(tmp1) + k + str(tmp4))
                if tmp3 == 24&nbs***bsp;tmp5 == 24&nbs***bsp;int(tmp6) == 24:
                    flag = True
if flag:
    print('true')
else:
    print('false')



发表于 2024-12-17 23:28:34 回复(0)
#!/user/local/bin/python3

##思路:穷举所有可能的组合
def get_num_combination(aList, step, repeat_flag, resultList, tempList):
    for i in range(len(aList)):
        ThisList=aList.copy()
        if step==1:
            tempList[step-1]=ThisList[i]
            resultList.append(tempList.copy())
        else:
            if repeat_flag:
                tempList[step-1]=ThisList[i]
            else:
                tempList[step-1]=ThisList.pop(i)
            get_num_combination(ThisList, step-1, repeat_flag, resultList, tempList)

##将所有可能的数字组合都列出来
numList=list(map(int,input().split()))
numcombinList=[]
tempList=[0,0,0,0]
get_num_combination(numList, 4, False, numcombinList, tempList)
#print(numcombinList)

##将所有可能的运算符组合都列出来
calculatedList=['+','-','*','/']
calcombinList=[]
tempList=['', '', '']
get_num_combination(calculatedList, 3, True, calcombinList, tempList)
#print(calcombinList)

##将所有可能的表达式组合起来,
# 考虑括号的情况。
# 对于像8/(3-8/3)这种虽然符合条件,但是计算机算出来是23.999999的情况,算通过。
# 表达式里面,如果除号后面的计算结果是0,跳过
find_flag='false'
for i in numcombinList:
    if find_flag=='true':
        break
    for j in calcombinList:
        tempStrList=[]
        tempStrList.append(str(i[0])+str(j[0])+str(i[1])+str(j[1])+str(i[2])+str(j[2])+str(i[3]))
        tempStrList.append('('+str(i[0])+str(j[0])+str(i[1])+')'+str(j[1])+str(i[2])+str(j[2])+str(i[3]))
        tempStrList.append('('+str(i[0])+str(j[0])+str(i[1])+str(j[1])+str(i[2])+')'+str(j[2])+str(i[3]))
        tempStrList.append(str(i[0])+str(j[0])+'('+str(i[1])+str(j[1])+str(i[2])+')'+str(j[2])+str(i[3]))
        tempStrList.append(str(i[0])+str(j[0])+'('+str(i[1])+str(j[1])+str(i[2])+str(j[2])+str(i[3])+')')
        tempStrList.append(str(i[0])+str(j[0])+str(i[1])+str(j[1])+'('+str(i[2])+str(j[2])+str(i[3])+')')
        tempStrList.append('('+str(i[0])+str(j[0])+str(i[1])+')'+str(j[1])+'('+str(i[2])+str(j[2])+str(i[3])+')')
        for k in tempStrList:
            if k.count('/(') > 0:
                index1=k.index('/(')
                index2=k.index(')',index1)
                if eval(k[index1+2:index2])==0:
                    break
            result=eval(k)
            if result==24&nbs***bsp;abs(result-24)<0.000001:
                find_flag='true'
                break
print(find_flag)

发表于 2024-12-16 08:45:53 回复(0)
好像写复杂了
from itertools import combinations
def find_method():
    for i in range(4):
        if 24 in values[i]:
           return f'{a[i][1]} {symbol[values[i].index(24)]} {a[i][0]}'
        for j in range(4):
            new_set = list(a[i])
            new_set.append(nums[j])
            if new_set.count(nums[j]) == nums.count(nums[j]):
                for m in range(len(values[i])):
                    if values[i][m] + nums[j] == 24:
                        return  f'{a[i][1]} {symbol[m]} {a[i][0]} + {nums[j]}'
                    elif values[i][m] - nums[j] == 24:
                        return f'{a[i][1]} {symbol[m]} {a[i][0]} - {nums[j]}'
                    elif values[i][m] * nums[j] == 24:
                        return f'( {a[i][1]} {symbol[m]} {a[i][0]} ) * {nums[j]}'
                    elif values[i][m] / nums[j] == 24:
                        return f'( {a[i][1]} {symbol[m]} {a[i][0]} ) / {nums[j]}'
        for j in range(len(a)):
            new_set = list(a[i])
            new_set.extend(list(a[j]))
            new_set.sort()
            if new_set == nums:
                for m in range(len(values[i])):
                    for n in range(len(values[j])):
                        if values[i][m] + values[j][n] == 24:
                            return f'{a[i][1]} {symbol[m]} {a[i][0]} {symbol[0]} {a[j][1]} {symbol[n]} {a[j][0]}'
                        elif abs(values[i][m]-values[j][n]) == 24:
                            if values[i][m] > values[j][n]:
                                return f'{a[i][1]} {symbol[m]} {a[i][0]} {symbol[0]} {a[j][1]} {symbol[n]} {a[j][0]}'
                            return f'{a[j][1]} {symbol[n]} {a[j][0]} {symbol[0]} {a[i][1]} {symbol[m]} {a[i][0]}'
                        elif values[j][n] * values[i][m] == 24:
                            return f'( {a[i][1]} {symbol[m]} {a[i][0]} ) {symbol[0]} ( {a[j][1]} {symbol[n]} {a[j][0]} )'
                        elif values[j][n] != 0:
                            if values[i][m] / values[j][n] == 24:
                                return f'( {a[i][1]} {symbol[m]} {a[i][0]} ) {symbol[0]} ( {a[j][1]} {symbol[n]} {a[j][0]} )'
                        elif values[i][m] != 0:
                            if values[j][n] / values[i][m] == 24:
                                return f'( {a[j][1]} {symbol[n]} {a[j][0]} ) {symbol[0]} ( {a[i][1]} {symbol[m]} {a[i][0]} )'
symbol = ['+', '-', '*', '/']
nums = list(map(int, input().strip().split()))
nums.sort()
a = list(combinations(nums, 2))
values = list()
for i in range(len(a)):
    b = list()
    b.append(sum(a[i]))
    b.append(abs(a[i][1]-a[i][0]))
    b.append(a[i][1] * a[i][0])
    if a[i][1] % a[i][0] == 0:
        b.append(int(a[i][1] / a[i][0]))
    values.append(b)
method = find_method()
if method == None:
    print('false')
else:
    #print(method)
    print('true')

发表于 2024-11-28 17:17:01 回复(0)
4 2 7 3 这条用例过不去,不知道为啥。。。24/27pass
def caculate(a,b):
    res=[]
    res.append(a+b)
    res.append(abs(a-b))
    res.append(a*b)
    if b!=0 and a%b==0 :
        res.append(a//b)
    elif a!=0 and b%a==0:
        res.append(b//a)
    return res

def twenty4(inPut):
    for i in range(3):
        for j in range(i,4):
            res1=caculate(inPut[i],inPut[j])
            set1={i,j}
            rest=[inPut[x] for x in list(set([0,1,2,3])-set1)]
            for ii in res1:
                res2=caculate(ii,rest[0])
                for jj in res2:
                    res3=caculate(jj,rest[1])
                    if 24 in res3:
                        return 'true'
    return 'false'

inPut=list(map(int,input().split()))
print(twenty4(inPut))
发表于 2024-11-07 19:48:40 回复(0)
import sys
def fun1(a,b):      #   返回两数+-*/结果列表
    x = [a+b,abs(a-b),a*b]
    if b!=0 and a%b == 0:
        x.append(a//b)
    elif b!= 0 and b%a == 0:
        x.append(b//a)
    return x
def fun(x):
    k = 'false'
    a  = [0,0]
    b = []
    for i in range(4):
        if k!= 'true':
            a[0] = x[i]  
            b = []  
            for j in range(i+1,4):           
                if j!= i  :
                    a[1] = x[j]
                    b = [x[ii] for ii in list(set([0,1,2,3])-set([i,j]))]                  
                    aa = fun1(a[0],a[1])
                    bb = fun1(b[0],b[1])
                    # print(a,b,aa,bb)   aa,bb分别存储两对数的+-*/运算结果
                    for i0 in aa:                                  
                        if  (set(fun1(24,i0)) & set(bb) )&nbs***bsp;(set(fun1(24,b[0])) & set(fun1(i0,b[1]))): 
                            # 若aa中有元素i0与24 +-*/ 后在bb 中 (即 4 = 2+2 )或i0与b中元素b[1] +-*/ 后 == 24+-*/b[0](即 4= 2+1 +1)                            
                            k = 'true'                           
                            break
                    if k=='true':
                        break                  
    print(k)
          
while True:
    try:
        xx = list(map(int,input().split()))
        fun(xx)

    except:
        break

发表于 2024-05-23 04:49:08 回复(0)
s=list(map(int,input().split()))

import copy
rl=[]
def fun(sl,rl=[]):
    if len(sl)==1:
        if sl[0]==24:
            return True
        else:
            return False

    for i in sl:
        sq=copy.deepcopy(sl)
        sq.remove(i)
        for j in sq:
            ss=copy.deepcopy(sq)
            ss.remove(j)
               
            if fun([i*j]+ss):
                return True
            if j!=0 and fun([i/j]+ss):
                return True
            if fun([i+j]+ss):
                return True
            if fun([i-j]+ss):
                return True
            else:
                ss
if fun(s):
    print('true')    
else:
    print('false')
发表于 2024-05-14 16:05:03 回复(0)
"""
实现功能,输入任意一个数组numbers,给一个目标数target_num
判断数组中的数经过四个运算符以及加括号运算能否运算出目标数
这个问题主要使用递归和穷举法
1.	首先生成四个数的全排列
2.	然后将每个排列都穷举运算
3.	将所有可能的计算并检查是否和目标值相等
4.	处理异常,除数为零时的做法,
5.	运算精度,截断误差的影响,最后与目标数比较时应该给一个小误差阈值。
以上第2步中涉及加括号运算问题,加括号的运算可以如下处理
考虑加括号的运算可以理解为将一列数中的任意两个相邻数取出运算,然后将结果放入原位置,并递归这一过程。这种递归式的分割方法是解决包含括号运算问题的典型思路。
以上包含了括号中多个运算数的情况,因为括号中多运算数时按照运算规则从前往后计算,以上方法包含从前往后加括号计算。
定义一个四个有序数的运算函数,任意相邻位置取出两个进行加减乘除运算,运算后放入原位置,进行递归,最终得到四个有序数在加括号且四个运算符下的所有可能的运算结果。
再对四个数生成的全排列全部进行有序数的运算,与目标值比较。
"""

import itertools  # 用于生成全排列

# 允许的运算符
operators = ['+', '-', '*', '/']


# 使用递归计算结果
def calculate(a, b, op):
    if op == '+':
        return a + b
    elif op == '-':
        return a - b
    elif op == '*':
        return a * b
    elif op == '/':
        if b == 0:
            return None  # 避免除零
        return a / b


# 递归计算所有可能的结果
def evaluate(numbers):
    # 如果只有一个数字,返回它
    if len(numbers) == 1:
        return [numbers[0]]

    results = []
    # 遍历所有可能的二元操作
    for i in range(1, len(numbers)):
        left_nums = numbers[:i]
        right_nums = numbers[i:]

        left_results = evaluate(left_nums)
        right_results = evaluate(right_nums)

        # 遍历所有运算符并计算结果
        for left_result in left_results:
            for right_result in right_results:
                for op in operators:
                    result = calculate(left_result, right_result, op)
                    if result is not None:
                        results.append(result)

    return results


# 检查是否可以运算出 target_num
def can_make_target(numbers, target_num):
    # 生成数字的所有排列
    permutations = itertools.permutations(numbers)

    # 遍历所有排列并计算结果
    for perm in permutations:
        results = evaluate(list(perm))
        for result in results:
            # 考虑浮点精度,浮点数运算的截断误差问题
            if abs(result - target_num) < 1e-6:  # 使用一个小的阈值
                return True

    return False


# numbers = [4, 7, 8, 6, 100]
# target_num = 124
# result = can_make_target(numbers, target_num)
# print(f"numbers:{numbers}\nCan make {target_num}:{result}")  # 输出 True 或 False


numbers = [int(i) for i in input().split(" ")]
result = can_make_target(numbers,  24)
print(str(result).lower())  # 输出true或false

发表于 2024-05-03 18:43:15 回复(0)
a, b, c, d = map(int,input().split())
A = [a, b, c, d]
B = ['+', '-', '*', '/']
count = 0
res = 0
for i in range(4):
    for j in range(4):
        for k in range(4):
            for l in range(4):
                if i != j and i != k and i != l and j != k and j != l and k != l:
                    for m in B:
                        for n in B:
                            for o in B:
                                count += 1
                                C1 = ['(', A[i], m, A[j], ')', n, A[k], o, A[l]]
                                C2 = ['(', A[i], m, A[j], n, A[k], ')', o, A[l]]
                                C3 = [A[i], m, A[j], n, A[k], o, A[l]]
                                C4 = [A[i], m, '(', A[j], n, A[k], ')', o, A[l]]
                                C5 = [A[i], m, '(', A[j], n, A[k], o, A[l], ')']
                                C6 = [A[i], m, A[j], n, '(', A[k], o, A[l], ')']
                                C1,C2,C3,C4,C5,C6 = map(str, C1),map(str, C2),map(str, C3),map(str, C4),map(str, C5),map(str, C6)
                                D1,D2,D3,D4,D5,D6 = ''.join(C1),''.join(C2),''.join(C3),''.join(C4),''.join(C5),''.join(C6)
                                DD = [D1, D2, D3, D4, D5, D6]
                                for ii in DD:
                                    try:
                                        E = eval(ii)
                                    except ZeroDivisionError:
                                        E = 'Error'  # 处理除数为0的情况
                                    if E == 24:
                                        res = 1
if res == 1:
    print('true')
else:
    print('false')


带括号多六倍,枚举一下。
发表于 2024-04-13 18:49:13 回复(0)
print('true') #幽默一下,可以通过18组用例
发表于 2024-01-05 15:55:20 回复(2)
利用逆波兰表达式(后缀表达式),省区了判断括号优先级的麻烦。
# 利用逆波兰表达式
def canExpAddOpe(exp_arr):
    stack_data_num = 0
    for chr_ in exp_arr:
        if(chr_ in "+-*/"):
            stack_data_num -= 1
        else:
            stack_data_num += 1
    return stack_data_num > 1

def computeExpression(exp_arr):
    data_stack = []
    for chr_ in exp_arr:
        if(chr_ in "+-*/"):
            data1 = data_stack.pop()
            data2 = data_stack.pop()
            if(chr_ == "+"):
                data_stack.append(data2+data1)
            elif(chr_ == "-"):
                data_stack.append(data2-data1)
            elif(chr_ == "*"):
                data_stack.append(data2*data1)
            else:
                if(data1 == 0): return -1
                data_stack.append(data2/data1)
        else:
            data_stack.append(int(chr_))
    return data_stack[0]
def can24Dot(data_arr,exp_arr):
    if(len(data_arr)!=0):
        for i in range(len(data_arr)):
            select_fig = data_arr[i]
            exp_arr.append(select_fig)
            data_arr.pop(i)
            if(can24Dot(data_arr,exp_arr)): return True
            data_arr.insert(i,select_fig)
            exp_arr.pop()
    can_add_ope = canExpAddOpe(exp_arr)
    if(can_add_ope):
        for ope_ in '+-*/':
            exp_arr.append(ope_)
            if(can24Dot(data_arr,exp_arr)): return True
            exp_arr.pop()
    if(len(data_arr)!=0&nbs***bsp;can_add_ope): return False
    if(computeExpression(exp_arr) == 24): return True
    return False

input_str = input()
input_int_arr = input_str.split()
if(can24Dot(input_int_arr,[])):
    print("true")
else:
    print("false")


发表于 2023-07-27 00:45:42 回复(0)
# 解决热门分享中没有考虑到带括号情况的BUG

arr = input().split()
def check_24(arr, exp=""):
    if len(arr) == 1:
        exp += arr[0]
        # 找出3个运算符所在位置
        flag = 0
        for i in range(len(exp)):
            if not exp[i].isdigit() and flag == 0:
                flag = 1
                s0 = i
                continue
            if not exp[i].isdigit() and flag == 1:
                flag = 2
                s1 = i
                continue
            if not exp[i].isdigit() and flag == 2:
                s2 = i
                break
        for exp_ in [  # 考虑各种带括号的形式,这里有很大优化空间,但是踩坑已经踩到吐血不想深究了
            exp,  # a + b + c + d
            f"({exp[:s1]}){exp[s1:]}",  # (a + b) * c + d
            f"{exp[:s1+1]}({exp[s1+1:]})",  # a + b * (c + d)
            f"({exp[:s1]}){exp[s1]}({exp[s1+1:]})",  # (a + b) * (c + d)
            f"({exp[:s2]}){exp[s2:]}",  # (a + b + c) * d
            f"{exp[:s0+1]}({exp[s0+1:]})",  # a * (b + c + d)
        ]:
            # 执行表达式,用try跳过/0的情况
            try:
                locals()["res"] = 0
                exec(f"res={exp_}")
            except:
                pass
            if locals()["res"] == 24:
                raise
    else:

        # 生成所有表达式
        for i in range(len(arr)):            
            check_24(arr[:i] + arr[i + 1 :], exp + arr[i] + "+")
            check_24(arr[:i] + arr[i + 1 :], exp + arr[i] + "-")
            check_24(arr[:i] + arr[i + 1 :], exp + arr[i] + "*")
            check_24(arr[:i] + arr[i + 1 :], exp + arr[i] + "/")
try:
    check_24(arr)
    print("false")
except:
    print("true")
发表于 2023-07-14 09:34:17 回复(0)
a = input().split()
res,l1 = [],[]
mark = [0]*4
cnt = 0
def dfs():
    global cnt
    if len(res)>0 and res[-1] == 24:
        # l1.append(res) # = 是浅拷贝。列表是可变对象,res的值会变回溯改为[]
        # s1 = set(res) #可以用元组来存值,元组是不可变对象,值不会被修改
        cnt +=1 # 数字为不可变对象,也可以用计数器来存返回值
        # l1.append(s1)
        return cnt

    for i in range(0,len(a)):
            for ys in ('+','-',"*",'/'):
                if mark[i] ==0 :
                    if len(res) == 0:
                        res.append(int(a[i]))
                        mark[i] =1
                    elif len(res)<4:
                        res.append(eval(str(res[-1])+ys+a[i]))
                        mark[i] =1
                    dfs()
                    res.pop()
                    mark[i] = 0

dfs()
print(str(bool(cnt)).lower())
发表于 2023-07-02 01:10:18 回复(0)
# 参考了楼下的思路 感谢dalao

numbers = list(map(int, input().strip().split(" ")))

has_cal = []


def cal_24(nums):
    if len(nums) == 1:
        return nums[0] == 24

    else:
        r1 = r2 = r3 = r4 = False
        for i in range(len(nums)):
            for j in range(len(nums)):
                if i != j:
                    temp = [nums[k] for k in range(len(nums))if k not in [i, j]]

                    cal_plus = nums[i] + nums[j]
                    if ([cal_plus, ] + temp)not in has_cal:
                        has_cal.append([cal_plus, ] + temp)
                        r1 = cal_24([cal_plus, ] + temp)

                    cal_plus = nums[i] - nums[j]
                    if ([cal_plus, ] + temp) not in has_cal:
                        has_cal.append([cal_plus, ] + temp)
                        r2 = cal_24([cal_plus, ] + temp)

                    cal_plus = nums[i] * nums[j]
                    if ([cal_plus, ] + temp) not in has_cal:
                        has_cal.append([cal_plus, ] + temp)
                        r3 = cal_24([cal_plus, ] + temp)

                    if nums[j] != 0:
                        cal_plus = nums[i] / nums[j]
                        if ([cal_plus, ] + temp) not in has_cal:
                            has_cal.append([cal_plus, ] + temp)
                            r4 = cal_24([cal_plus, ] + temp)
                if any([r1, r2, r3, r4]):
                    return any([r1, r2, r3, r4])
        return any([r1, r2, r3, r4])


print(str(cal_24(numbers)).lower())

发表于 2023-05-18 17:29:24 回复(0)
import sys

# 利用递归和回溯
def can_get_24(nums):
    if len(nums) == 1:
        return abs(nums[0] - 24) < 1e-6

    for i in range(len(nums)):
        for j in range(len(nums)):
            if i != j:
                new_nums = [nums[k] for k in range(len(nums)) if k != i and k != j]
                # 递归调用 can_get_24 函数,传递更新后的数字列表 new_nums。如果返回值为True,表示可以得到24,则立即 返回True。否则,我们通过 new_nums.pop() 将最后添加的结果移出列表,以便尝试其他运算
                # 加法
                new_nums.append(nums[i] + nums[j])
                if can_get_24(new_nums):
                    return True
                new_nums.pop()

                # 减法
                new_nums.append(nums[i] - nums[j])
                if can_get_24(new_nums):
                    return True
                new_nums.pop()

                # 乘法
                new_nums.append(nums[i] * nums[j])
                if can_get_24(new_nums):
                    return True
                new_nums.pop()

                # 除法
                if nums[j] != 0:
                    new_nums.append(nums[i] / nums[j])
                    if can_get_24(new_nums):
                        return True
                    new_nums.pop()

    return False


# 获取输入的4个整数
nums = list(map(int, input().split()))

# 检查是否能得到24
result = can_get_24(nums)

# 输出结果
if result:
    print("true")
else:
    print("false")

发表于 2023-05-09 18:39:31 回复(0)