描述
给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。
输入描述:
读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。
输出描述:
对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false
示例1
输入:
7 2 1 10
输出:
true
理解
穷举所有的算数组合。但由于可能存在的括号,导致生成这样的运算操作,以及求解都麻烦。在这里用到了逆波兰表达式(后缀表达式),无需加入括号且方便穷举。
代码
# 利用逆波兰表达式
# 逆波兰表达式继续插入运算符是否合法
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 or 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")
另一种思路:行为描述
看到其它dfs的方法,从算法的行为层面上进行dfs,避开了抽象的数学表达式。实际上24点游戏,就是拿4张纸牌互相组合,将两张牌运算后合成新的“牌”。看来很多时候思考问题,不必从抽象层面思考,而要想想其实际意义,其现实的、物理的含义是什么。