首页 > 试题广场 >

24点游戏算法

[编程题]24点游戏算法
  • 热度指数:139151 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算。
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。

输入描述:

读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。



输出描述:

对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false

示例1

输入

7 2 1 10

输出

true
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)
def func1(nums, val):
    # 这个函数对3个数字的24点游戏是通用的
    if len(nums) == 1 and nums[0] == val:
        return True
    else:
        for i in range(len(nums)):
            a = nums[:i]+nums[i+1:]
            b = nums[i]
            if func1(a, val+b)&nbs***bsp;func1(a, val-b)&nbs***bsp;((func1(a, val*b)&nbs***bsp;func1(a, val/b)) if b != 0 else False):
                return True
        return False


def func2(nums):
    # 这个函数将4个数字转化为3个数字
    res = []
    for i in range(len(nums)):
        for j in range(i+1, len(nums)):
            tmp = nums[:]
            tmp.remove(nums[i])
            tmp.remove(nums[j])
            res.append(tmp + [nums[i] + nums[j]])
            res.append(tmp + [nums[i] - nums[j]])
            res.append(tmp + [nums[i] * nums[j]])
            res.append(tmp + [nums[i] / nums[j]])
    return res


num = list(map(int, input().split()))
if True in [func1(i, 24) for i in func2(num)]:
    print('true')
else:
    print('false')

发表于 2023-04-29 13:47:13 回复(0)
# 想了下可以用后缀表达式做
# 对于abcd四个数的后缀表达式,有5个地方可以插入运算符
# ab[]c[][]d[@][][],其中[]表示一个可能的运算符位置,[@]表示一个固定的运算符位置
# 对于四个数,总共有三个运算符,剩余两个排列组合即可

def rpn_eval(str1:str,str2:str,ope:str)->str:
    try:
        return str(eval(str1+ope+str2))
    except ZeroDivisionError:
        return '0'

n=[i for i in input().strip().split(' ')]

# 数字排列组合
nums=[]
for i in range(4):
    for ii in range(4):
        for iii in range(4):
            for iiii in range(4):
                if len(set([i,ii,iii,iiii]))==4:
                    nums.append([n[i],n[ii],n[iii],n[iiii]])

# 运算符排列组合
opers=['+','-','*','/']
opes=[]
for i in range(5):
    for ii in range(5):
        for s in opers:
            for ss in opers:
                if i!=ii:
                    temp=['','','','','']
                    temp[i],temp[ii]=s,ss
                    opes.append(temp)

# 组合后缀表达式
calcs=[]
for n in nums:
    for o in opes:
        for s in opers:
            calcs.append([n[0],n[1],o[0],n[2],o[1],o[2],n[3],s,o[3],o[4]])

# 计算后缀表达式
ans='false'
for calc in calcs:
    res=0
    new=[]
    for s in calc:
        if s=='':
            continue
        if s.isdigit():
            new.append(s)
        else:
            res=rpn_eval(new[-2],new[-1],s)
            new.pop()
            new[-1]=res
    if new[-1]=='24':
        ans='true'
        break
print(ans)



发表于 2023-04-28 15:21:46 回复(0)
看了下python排行答案全是错的 不考虑()
list1 = list(map(int, input().split()))

def is24(nums, aa, bb, cc, dd):
    def a_b(a, b, p):
        if p == 1:
            return a + b
        elif p == 2:
            return a - b
        elif p == 3:
            return a * b
        elif p == 4:
            return a / b

    go_list = nums.copy()
    t_num = 0
    n1 = go_list[aa[0] - 1]
    n2 = go_list[aa[1] - 1]
    go_list.remove(n1)
    go_list.remove(n2)
    t_num = a_b(n1, n2, bb)
    temp_list = []
    temp_list.append(t_num)
    for oo in go_list:
        temp_list.append(oo)

    go_list = temp_list
    n1 = go_list[cc[0] - 1]
    n2 = go_list[cc[1] - 1]
    go_list.remove(n1)
    go_list.remove(n2)
    t_num = a_b(n1, n2, dd)
    temp_list = []
    temp_list.append(t_num)
    for oo in go_list:
        temp_list.append(oo)
    go_list = temp_list
    # print(nums)
    if (
        float(go_list[0] + go_list[1]) == 0
        or float(go_list[0] * go_list[1] - 24) == 0
        or float(go_list[0] - go_list[1] - 24) == 0
        or float(go_list[1] - go_list[0] - 24) == 0
        or float(go_list[0] / go_list[1] - 24) == 0
        or float(go_list[1] / go_list[0] - 24) == 0
    ):
        return True
    else:
        return False

a = [
    (1, 2),
    (1, 3),
    (1, 4),
    (2, 1),
    (2, 3),
    (2, 4),
    (3, 1),
    (3, 2),
    (3, 4),
    (4, 1),
    (4, 2),
    (4, 3),
]
b = (1, 2, 3, 4)
c = [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
d = [1, 2, 3, 4]

solut = []
for i in a:
    for j in b:
        for k in c:
            for l in d:
                solut.append((i, j, k, l))
mark = 0
for i in solut:

    try:
        uu = is24(list1, i[0], i[1], i[2], i[3])
    except:
        pass
    if uu:
        mark = 1
        print("true")
        break
if mark == 0:
    print("false")



发表于 2023-03-25 02:42:02 回复(0)
def solution(l,target):
    if len(l) == 1:
        return l[0] == target
    else:
        for i in range(len(l)):
            l1 = l[:i] + l[i+1:]
            n = l[i]
            if solution(l1,target+n)&nbs***bsp;solution(l1,target-n)&nbs***bsp;solution(l1,target*n)&nbs***bsp;solution(l1,target/n):
                return True
while True:
    try:
        l = list(map(int,input().split()))
        if solution(l,24):
            print('true')
        else:
            print('false')
    except:
        break

发表于 2023-03-01 23:50:06 回复(1)
因为只有4个数,所以暴力穷举也不会耗时很久
先用permutations函数求出四个数的全排列,然后对每一种排列进行加减乘除运算。
由于使用了全排列:
    ①可以排除掉可能会除出小数的情况,因为这里的先除后乘会在某一个排列里变成先乘后除,所以只需要把可以除尽的情况加入新的列表
    ②可以不需要考虑在哪里加括号的问题,因为加括号实际就是重排序列计算
因为这里只需要判断能不能算出24,当有一个计算结果为24时就可以终止循环
from itertools import permutations
nums=list(map(int,input().split(' ')))
l=list(permutations(nums,4))
#print(l)
flag=1
for i in l:
    re=[i[0]]
    for j in i[1:]:
        tmp=[]
        for k in re:
            if k%j==0:
                tmp.extend([k+j,k-j,k*j,k//j])
            else:
                tmp.extend([k+j,k-j,k*j])
        re=tmp
    for j in re:
        if j==24:
            print('true')
            flag=0
            break
    if flag==0:
        break
if flag==1:
    print('false')


发表于 2023-02-23 17:46:34 回复(0)