《算法竞赛·快冲300题》每日一题:“凑二十四”

news/2024/7/20 23:14:22 标签: 算法, 深度优先, leetcode

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

凑二十四” ,链接: http://oj.ecustacm.cn/problem.php?id=1793

题目描述

【题目描述】 给你n个数字,你需要在n-1个间隔中添加符号+、-、×,按照正常优先级计算结果。请你输出有多少种方案,计算结果等于24。
【输入格式】 第一行为正整数n(2≤n≤10)。第二行n个正整数表示给定的n个数字,数字不超过50。
【输出格式】 输出一个数字表示答案。
【输入样例】

5
2 4 6 8 16

【输出样例】

2

题解

   如果尝试所有可能组合,共有多少种组合?最多n=10个数字时,需要添加9个符号,共 3 9 = 19683 3^9=19683 39=19683种组合,并不多。
  用DFS搜索所有可能组合。由于只有19683种情况,不用剪枝。
  代码用dfs()搜索所有符号组合。对每个组合,用check()检查计算结果是否等于24。先计算乘法,再计算加减。下面的代码用了简单直接的模拟法。先处理表达式中的乘法,对两个数做乘法时,把计算结果存在后面,前面置零,并把符号改为前面的加减,例如3+4×5,先处理乘法,转换为3+0+20。
  check()也有其他写法,例如先把表达式(称为中缀表达式)转为逆波兰表达式,然后用栈来计算逆波兰表达式。因为比较繁琐,这里没有给出代码。
【重点】 DFS 。

C++代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, a[11];
int op[11];               //第i个间隔的符号 + - * = 0 1 2
int ans;
ll check(){   //先计算*,再计算+-
    ll t[11] = {0}, t_op[11] = {0};
    for(int i=1; i<=n; i++)
        t[i] = a[i], t_op[i] = op[i];
    //先处理乘号:把乘积结果存入t[i+1]、t[i]设置为0、符号沿用前面的符号
    for(int i = 1; i < n; i++)
        if(t_op[i] == 2)
            t[i+1] *= t[i], t[i] = 0, t_op[i] = t_op[i-1];
    //最后加减
    ll sum = t[1];
    for(int i = 1; i < n; i++){
        if(t_op[i] == 0)  sum += t[i+1]; //加
        else sum -= t[i+1];              //减
    }
    return sum;
}
void dfs(int depth){
    if(depth == n){
        if(check() == 24)   ans++;
        return;
    }
    for(int i = 0; i <= 2; i++) {   //继续添加下一个符号
        op[depth] = i;
        dfs(depth + 1);
    }
}
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++)    cin >> a[i];
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

Java代码

import java.util.Scanner;
public class Main {
    static int n, a[] = new int[11], op[] = new int[11]; // 第i个间隔的符号 + - * = 0 1 2
    static int ans;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        for (int i = 1; i <= n; i++)   a[i] = in.nextInt();
        dfs(1);
        System.out.println(ans);
        in.close();
    }
    static long check() { // 先计算*,再计算+-
        long[] t = new long[11];
        int[] t_op = new int[11];
        for (int i = 1; i <= n; i++) {
            t[i] = a[i];
            t_op[i] = op[i];
        }
        // 先处理乘号:把乘积结果存入t[i+1]、t[i]设置为0、符号沿用前面的符号
        for (int i = 1; i < n; i++) {
            if (t_op[i] == 2) {
                t[i + 1] *= t[i];
                t[i] = 0;
                t_op[i] = t_op[i - 1];
            }
        }
        // 最后加减
        long sum = t[1];
        for (int i = 1; i < n; i++) {
            if (t_op[i] == 0) sum += t[i + 1]; // 加
            else              sum -= t[i + 1]; // 减
        }
        return sum;
    }
    static void dfs(int depth) {
        if (depth == n) {
            if (check() == 24)   ans++;
            return;
        }
        for (int i = 0; i <= 2; i++) { // 继续添加下一个符号
            op[depth] = i;
            dfs(depth + 1);
        }
    }
}

Python代码

n = int(input())
a = [0]+list(map(int, input().split()))     #输入到a[1]-a[10]
op = [0] * 11                               # 第i个间隔的符号 + - * = 0 1 2
ans = 0
def check():# 先计算*,再计算+-
    t = [0] * 11
    t_op = [0] * 11
    for i in range(1, n+1):
        t[i] = a[i]
        t_op[i] = op[i]
    # 先处理乘号:把乘积结果存入t[i+1]、t[i]设置为0、符号沿用前面的符号
    for i in range(1, n):
        if t_op[i] == 2:
            t[i+1] *= t[i]
            t[i] = 0
            t_op[i] = t_op[i-1]
    # 最后加减
    sum = t[1]
    for i in range(1, n):
        if t_op[i] == 0: sum += t[i+1]  # 加
        else:            sum -= t[i+1]  # 减
    return sum
def dfs(depth):
    global ans
    if depth == n:
        if check() == 24:   ans += 1
        return
    for i in range(3):                  # 继续添加下一个符号
        op[depth] = i
        dfs(depth + 1)
dfs(1)
print(ans)

http://www.niftyadmin.cn/n/4965085.html

相关文章

stm32串口通信(PC--stm32;中断接收方式;附proteus电路图;开发方式:cubeMX)

单片机型号STM32F103R6: 最后实现的效果是&#xff0c;开机后PC内要求输入1或0&#xff0c;输入1则打开灯泡&#xff0c;输入0则关闭灯泡&#xff0c;输入其他内容则显示错误&#xff0c;值得注意的是这个模拟的东西只能输入英文 之所以用2个LED灯是因为LED电阻粗略一算就是1…

Spring Boot 整合MyBatis-Plus

&#x1f600;前言 本篇博文是关于Spring Boot 整合MyBatis-Plus的&#xff0c;希望你能够喜欢&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的…

spark中排查Premature EOF: no length prefix available

报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…

Node基础--Node简介以及安装教程

1.Node简介 Node.js发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;是一个基于Chrome V8引擎的JavaScript运行环境&#xff0c;使用了一个事件驱动、非阻塞式I/O模型&#xff0c;让JavaScript 运行在服务端的开发平台&#xff0c;它让JavaScript成为与PHP、Python、Pe…

openjdk 安装包下载地址

源码 https://github.com/openjdk/jdk 官网下载地址 Archived OpenJDK GA Releases 20.0.1 (build 20.0.19)Windows64-bitzip (sha256) 188MMac/AArch6464-bittar.gz (sha256) 184MMac/x6464-bittar.gz (sha256) 186MLinux/AArch6464-bittar.gz (sha256) 187MLinux/x6464-bit…

Qt 正则(数据格式校验、替换指定格式数据、获取匹配数据)

头文件引用 #include <QRegExp>初始化QRegExp实列 QRegExp re("^\\d{1,3},\\d{1,3}$");数据格式验证 QRegExp re("^\\d{1,3},\\d{1,3}$"); QString msg "12,33"; if(re.exactMatch()){// 验证通过 }else{//验证不通过 }替换数…

Python Web开发技巧X

目录 select_related 和 prefetch_related 生成器对象的三种创建方式 classmethod和staticmethod __class__属性 python创建一个类会依次去调用哪些方法 __new__和__init__实现单例模式的饿汉式和懒汉式 select_related 和 prefetch_related select_related 和 prefetch_…

基于React实现无限滚动的日历详细教程,附源码【手写日历教程第二篇】

前言 最常见的日历大部分都是滚动去加载更多的月份&#xff0c;而不是让用户手动点击按钮切换日历月份。滚动加载的交互方式对于用户而言是更加丝滑和舒适的&#xff0c;没有明显的操作割裂感。 那么现在需要做一个这样的无限滚动的日历&#xff0c;前端开发者应该如何去思考…