IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 2022中兴捧月 限时编程 第一场 24点游戏 -> 正文阅读

[C++知识库]2022中兴捧月 限时编程 第一场 24点游戏

吐槽

读完题眼前一亮,这不就是24点游戏嘛,小时候和我弟玩过。吐槽一下中兴这个网页编辑器怎么就没法输出看结果呢?我人麻了,编辑器只能给我反馈一个“未通过”,我想输出一下中间结果看一下也不行!?看了半个多小时才发现除法可能会除以0(某两个相等的数相减,然后作为被除数这种情况)。。。。 还是太菜了,除以0都能写得出来。。。

题意

给定4个数,是否能用算术运算(±*/和括号)得到24?

分析

首先想到的是搜索,前半个小时一直在尝试深度优先搜索去尝试所有情况,但是代码越写越臭,直奔上百行去了,而且也A不掉。然后就仔细想了想以前玩24点游戏,我是怎么快速判断当前4张牌能够凑出24的?应该是先试探2张牌能凑出什么,然后往多了考虑3张牌、4张牌能凑出什么。

于是得出了最终的解决方案,有点动态规划的思想:

定义一个二维数组 m a r k [ i ] [ j ] mark[i][j] mark[i][j]表示 i i i这个状态能否凑出 j j j这个数字。由于数组很大,不妨把第二维换成 m a p map map,反正只是用来标记。其中 i i i是二进制位压缩的牌集合,例如 i = ( 10 ) 10 = ( 1010 ) 2 i=(10)_{10}=(1010)_2 i=(10)10?=(1010)2?表示取第1和第3张牌。然后就是1张牌、2张牌、3张牌、4张牌依次考虑能凑出来多少。

例如考虑3张牌能凑出来啥的时候,一定是由2张牌和1张牌计算而来的,而4张牌可能是3+1张牌或2+2张牌。

代码

#include <bits/stdc++.h>
using namespace std;

unordered_map<int, bool> mark[16];

void merge(int status1, int status2){
    int status = (status1 | status2);
    for (auto &x : mark[status1]){
        for (auto &y : mark[status2]){
            mark[status][x.first + y.first] = true;
            mark[status][abs(x.first - y.first)] = true;
            mark[status][x.first * y.first] = true;
            if (y.first > 0 && x.first % y.first == 0)
                mark[status][x.first / y.first] = true;
            if (x.first > 0 && y.first % x.first == 0)
                mark[status][y.first / x.first] = true;
        }
    }
}

bool damage(vector<int> &power){
    for (int i = 0; i < 16; i++)
        mark[i].clear();
    // 1 nums
    for (int i = 0; i < 4; i++)
        mark[1 << i][power[i]] = true;
    // 2 nums
    for (int i = 0; i < 4; i++)
        for (int j = i + 1; j < 4; j++)
            merge(1 << i, 1 << j);
    // 3 nums
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            for (int k = 0; k < 4; k++)
                if (i != j && j != k && k != i)
                    merge((1 << i) | (1 << j), 1 << k);
    // 4 nums
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            for (int k = 0; k < 4; k++)
                for (int t = 0; t < 4; t++)
                    if (i != j && i != k && i != t && j != k && j != t && k != t)
                    {
                        merge((1 << i) | (1 << j), (1 << k) | (1 << t));
                        merge((1 << i) | (1 << j) | (1 << k), 1 << t);
                    }
    return mark[15].count(24) > 0;
}

// 本地测试:
int main()
{
    vector<int> power({1, 1, 2, 7});
    cout << damage(power) << endl;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:24:29  更:2022-04-26 11:26:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:59:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码