【刷题汇总--游游的you、腐烂的苹果、孩子们的游戏(圆圈中最后剩下的数)】

C++日常刷题积累

  • 今日刷题汇总 - day005
    • 1、游游的you
      • 1.1、题目
      • 1.2、思路
      • 1.3、程序实现 - 蛮力法
      • 1.4、程序实现 - 贪心(优化)
    • 2、腐烂的苹果
      • 2.1、题目
      • 2.2、思路
      • 2.3、程序实现 - bfs
    • 3、孩子们的游戏(圆圈中最后剩下的数)
      • 3.1、题目
      • 3.2、思路
      • 3.3、程序实现 -- 环形链表
      • 3.4、程序实现 -- 约瑟夫环(动态规划法)
    • 4、题目链接

今日刷题汇总 - day005

1、游游的you

1.1、题目

在这里插入图片描述
在这里插入图片描述

1.2、思路

读完题知道,属于是贪心加模拟类的题型,那么肯定要满足you次数最多,再拼接oo满足最大分数的思想。其次,蛮力法我也写了,不过超出题目限制的空间范围了,思路就是按照题目模拟即可直接贴出来就不多说了。接下来,结合预处理方式,实现贪心的思路,既然我们需要you最大化,那么贪心的思想就是求you的最大次数,观察示例可知,you的次数是同时消耗a,b,c的次数,所以you的最大次数等于a,b,c中的最小值,其次,值得注意的是oo是1分,而ooo是2分,oooo是3分,可以推出oo的最大分数为b-1次数。然后,我们会先拼接you,会同时消耗b,那么oo最大分数就变成了b减去拼接you用掉o的次数,再-1即可。所以,最后的最大分数就等于you + oo的分数。接下来,具体看程序实现。

1.3、程序实现 - 蛮力法

就是模拟实现,过程略。

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> y;
    stack<int> o;
    stack<int> u;
    int q = 0;
    int a = 0;
    int b = 0;
    int c = 0;
    cin >> q;
    while (q--) {
        cin >> a >> b >> c;
        while (a) {
            y.push(a--);
        }
        while (b) {
            o.push(b--);
        }
        while (c) {
            u.push(c--);
        }
        int you = 0;
        while (!y.empty() && !o.empty() && !u.empty()) {
            y.pop();
            o.pop();
            u.pop();
            you += 2;
        }
        while (!y.empty()) {
            y.pop();
        }
        int oo = 0;
        int m = 0;
        int flag = 0;
        while (!o.empty()) {
            flag = 1;
            o.pop();
            m++;
        }
        if (flag) oo = m - 1;
        else oo = m;
        while (!u.empty()) {
            u.pop();
        }
        cout << (you + oo) << endl;
    }
    return 0;
}

在这里插入图片描述

在这里插入图片描述

1.4、程序实现 - 贪心(优化)

首先,按照题目要求,编写输入q表示访问次数,也就是a,b,c的输入次数,那么采用预处理方法,输入一次处理一次。

#include <iostream>
using namespace std;

int main()
{
    int q = 0;
    cin >> q;
    int a,b,c;
    while(q--)
    {
        
    }
    return 0;
}

接着,处理a,b,c和you与oo的次数与分数的关系。定义变量you统计当前预处理的a,b,c中you的分数,通过上述思路分析思考得知,you的最大分数就等于a,b,c的最小次数乘以2(2表示的是它的分之),即:you最大分数 = 次数 X 分值即可。同理,思路中分析得知,oo具有b-1的性质,且you会消耗o的次数即b的次数,即:oo的最大分数,定义变量ooo = b - 1 - (you/2)即可。最后,输出每一次预处理的结果you + ooo即可。

#include <iostream>
using namespace std;

int main()
{
    int q = 0;
    cin >> q;
    int a,b,c;
    while(q--)
    {
        cin >> a >> b >> c;
        int you = min(a,min(b,c)) * 2;
        int ooo = max(b-(you/2)-1,0);
        cout << (you + ooo) << endl;
    }
    return 0;
}

在这里插入图片描述

2、腐烂的苹果

2.1、题目

在这里插入图片描述

2.2、思路

读完题,第一反应就是之前写过的dfs算法思路,再次理解题目要求,0,1,2分别表示空格、好苹果、坏苹果且是随机的(多个2,多个0,多个1),然后一样四个方向每分钟(理解为一次操作)进行传播(可以理解为搜索),然后求多少次传播操作后没有好苹果,或遍历完后传播不到的好苹果的情况返回-1即可。然后,再根据示例分析,这里适用dfs是不适用的,属于是一圈一圈的传播,而不是一个一个的,那么这里需要用到多源bfs思路。也就是需要满足同时一次操作对于多个坏苹果2进行它周围传播的情况,那么我们可以把同一次操作中所有的2坏苹果放进一个队列里,就可以实现每一次出队列就可同时操作多个2坏苹果,其次,每一次操作就是一次传播所以用一个变量count记录坏苹果传播的次数,但是注意的是外层传播时注意边界控制。然后,传播到空格0,不管,传播到1好苹果则,将1置为2或者标记为已传播(我这里才用标记),然后继续把这个被传播的好苹果标记后,进入坏苹果队列,继续排序传播即可。遍历传播结束后,最后再遍历二维数组判断是否还有1好苹果,则返回-1即可,否则输出count传播次数。
由于不好理解,我简单画个图,便于理解:
在这里插入图片描述
在这里插入图片描述
接下来,就是程序实现。

2.3、程序实现 - bfs

首先,按照采用bfs思路的需求,编写需要的方向数组dx和dy,定义m,n计算二维数组的大小方便执行遍历(访问)操作,其次,这里采用布尔类型数组vis标记法表示是否已传播,然后定义坏苹果队列badapple,这里pair<int,int>因为需要的下标所以是用pair存放坏苹果的行和列即可。然后,遍历二维数组将坏苹果进队列。

class Solution
{
    int m,n;
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    bool vis[1001][1001] = {false};
    queue<pair<int,int>> badapple;

public:
    int rotApple(vector<vector<int> >& grid)
    {
        n = grid.size();
        m = grid[0].size();

        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j<m;j++)
            {
                if(grid[i][j] == 2)
                    badapple.push({i,j});
            }
        }
};

接着,创建count计数传播次数,因为是相邻之间的传播所以可以利用传播次数就是输出结果。
然后,只要队列中有坏苹果则执行传播,即出一层坏苹果且用sz保存当前这一层有几个坏苹果,以便依次执行上下左右的传播操作,即有多少个坏苹果就执行多少次传播,实现模拟同时一层坏苹果的传播。然后if(x >=0 && x < n && y >=0 && y < m && grid[x][y] == 1 && !vis[x][y]),进行边界控制防止出界且为好苹果且未被标记,则将它标记为已传播,再将它进队列,成为理解的下一层将要传播得坏苹果之一,等待sz次后,完成所有得第二层坏苹果,依次类推,直到传播结束。

class Solution
{
    int m,n;
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    bool vis[1001][1001] = {false};
    queue<pair<int,int>> badapple;

public:
    int rotApple(vector<vector<int> >& grid)
    {
        n = grid.size();
        m = grid[0].size();

        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j<m;j++)
            {
                if(grid[i][j] == 2)
                    badapple.push({i,j});
            }
        }

        int count = 0;
        while(badapple.size())
        {
            count++;
            int sz = badapple.size();
            while(sz--)
            {
                auto [a,b] = badapple.front();
                badapple.pop();
                for(int k = 0; k < 4;k++)
                {
                    int x = a + dx[k];
                    int y = b + dy[k];
                    if(x >=0 && x < n && y >=0 && y < m && grid[x][y] == 1 && !vis[x][y])
                    {
                        vis[x][y] = true;
                        badapple.push({x,y});
                    }                  
                }
            }
        }
    }
};

传播结束有两种情况,要么当前层的所有坏苹果的下一次传播单元(数组下标)都是空格0,要么就是全部坏苹果被传播完毕(遍历完)。最后,只需要再次遍历这个二维数组判断是都还有未被感染的好苹果且为被标记,有则返回-1,否则就是输出count-1即可。

class Solution
{
    int m,n;
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    bool vis[1001][1001] = {false};
    queue<pair<int,int>> badapple;

public:
    int rotApple(vector<vector<int> >& grid)
    {
        n = grid.size();
        m = grid[0].size();

        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j<m;j++)
            {
                if(grid[i][j] == 2)
                    badapple.push({i,j});
            }
        }

        int count = 0;
        while(badapple.size())
        {
            count++;
            int sz = badapple.size();
            while(sz--)
            {
                auto [a,b] = badapple.front();
                badapple.pop();
                for(int k = 0; k < 4;k++)
                {
                    int x = a + dx[k];
                    int y = b + dy[k];
                    if(x >=0 && x < n && y >=0 && y < m && grid[x][y] == 1 && !vis[x][y])
                    {
                        vis[x][y] = true;
                        badapple.push({x,y});
                    }                  
                }
            }
        }

        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j<m;j++)
            {
                if(grid[i][j] == 1 && !vis[i][j])
                    return -1;
            }
        }
        return count - 1;
    }
};

在这里插入图片描述

在这里插入图片描述

3、孩子们的游戏(圆圈中最后剩下的数)

3.1、题目

在这里插入图片描述

3.2、思路

读完题,立马知道了属于是之前写过的杨辉三角问题同样经典的约瑟夫环问题了。题目意思跟大家熟悉的数字炸弹游戏类似的规则,首先需要一个随机数m,然后这里是按照从0开始报数,让其后报数为m-3的小朋友退出,直到剩下最后一个小朋友即可。那么,对于约瑟夫问题可以采用蛮力法模拟实现,我这里就是使用环形链表来实现,其次还可以通过像利用杨辉三角的性质(状态方程)一样,结合约瑟夫环的规律递推(动态规划)求解。首先,链表方法,由于题目中已知小朋友的编号是有序的0~n-1,所以直接先让其进链表即可,然后判断m-1位置时,让其该位置释放掉即可,直到剩下最后一个小朋友的编号输出即可。值得注意的是需要处理一些细节等,如需要让被释放的位置的下一个位置作为计数的开始,所以需要一个it变量记录,变化的计数位置(可以巧妙的利用迭代器)。
然后,对于递推(动态规划法),跟之前写过的最小花费爬楼梯套路是一样的需要确定动态规划的状态表示以及状态转移方程。那么就来推理dp[i]和dp[n],为了方便理解画个图理解:
在这里插入图片描述

3.3、程序实现 – 环形链表

首先,我们建立链表,将编号插入链表。

class Solution {
  public:
    int LastRemaining_Solution(int n, int m)
    {
        list<int> lt;
        for (int i = 0; i < n; i++)
        {
            lt.push_back(i);
        }
    }
};

然后,我们利用迭代器变量it,记录按照规则走的位置,走到m-1位置处,直接用it.erase删除释放即可,值得注意的是,当调用 lt.erase(it) 删除元素后,返回的迭代器是指向被删除元素之后的那个元素的迭代器。因此,在删除元素后,不需要再手动将 it 设置为 lt.begin(),因为 it 已经自动更新为指向下一个元素的迭代器(如果存在的话)。所以,在删除元素后直接进行下一次循环即可。
另外,如果实现的循环呢?判断it遍历到end处就使它置begin位置即可。所以链表模拟相对于数组模拟,迭代器相对更好用。依次类推,遇见m-1就删除,直到链表中剩下一个编号,返回即可。

class Solution {
  public:
    int LastRemaining_Solution(int n, int m)
    {
        list<int> lt;
        for (int i = 0; i < n; i++)
        {
            lt.push_back(i);
        }
        auto it = lt.begin();
        while (lt.size() > 1)
        {
            for (int count = 1; count < m; ++count)
            {
                ++it;
                if (it == lt.end())
                {
                    it = lt.begin();
                }
            }
            it = lt.erase(it);
            if (it == lt.end())
                it = lt.begin();
        }
        return *it;
    }
};

在这里插入图片描述
在这里插入图片描述

3.4、程序实现 – 约瑟夫环(动态规划法)

接着,动态规划重要的在于分析和理解,状态表示以及状态转移方程,程序就相对简单了。
在这里插入图片描述
在这里插入图片描述
接着按照推导的方程写好程序即可。只需要说一下为什么这里%上的 i,其实就是推导出的dp[n] = (dp[n-1] + m)%n;只是把n换成每一次循环求的 i 而已,表示求每一步的映射关系。

class Solution {
public:
    int dp[5001];
    int LastRemaining_Solution(int n, int m)
    {
        dp[1] = 0;
        for(int i = 2;i <= n;i++)
            dp[i] = (dp[i-1] + m) % i;
        return dp[n];
    }
};

在这里插入图片描述

还可以进一步空间优化,直接控制变量即可。总结模拟就是老实的遍历删除,动态规划就是找规律,推导方程求解。

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        int f = 0;
        for(int i = 2;i <= n;i++)
            f = (f + m) % i;
        return f;
    }
};

在这里插入图片描述
在这里插入图片描述

4、题目链接

游游的you
腐烂的苹果
孩子们的游戏(圆圈中最后剩下的数)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/775407.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html+js+css在线倒计时

代码在图片后面 点赞加关注 谢谢大佬照顾&#x1f61c; 图例 时间到前 时间到后 源代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width,…

分支与循环

目录 1. if语句 1&#xff09;if 2) else 3&#xff09;分支中包含多条语句 4&#xff09;if嵌套 2.关系操作符 3.条件操作符 4.逻辑操作符&#xff1a;&& || ! 1) 逻辑取反运算符 !​编辑 2 与运算符​编辑 3) 或运算符​编辑 4) 闰年的判断 5) 短路 …

如何使用 SwiftUI 构建 visionOS 应用

文章目录 前言WindowsVolumes沉浸式空间结论 前言 Apple Vision Pro 即将推出&#xff0c;现在是看看 SwiftUI API 的完美时机&#xff0c;这使我们能够将我们的应用程序适应 visionOS 提供的沉浸式世界。苹果表示&#xff0c;构建应用程序的最佳方式是使用 Swift 和 SwiftUI。…

鸿蒙本地签名不匹配问题

连接鸿蒙手机运行项目报如下错误 这是由于本地签名和鸿蒙设备签名不匹配导致的&#xff0c;需要注释掉如下代码&#xff0c;选择file project 自动签名 勾选auto选项&#xff0c;会在build-profile.json5中生成一个签名&#xff0c;然后运行就ok了~

NXP i.MX8系列平台开发讲解 - 3.18 Linux tty子系统介绍(一)

专栏文章目录传送门&#xff1a;返回专栏目录 Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 目录 1. TTY 起源 2. Linux 系统中的TTY 2.1 Linux TTY 设备形式 2.2 Linux TTY framework 2.3 驱动核心相关文件…

「植物大战僵尸杂交版」保姆级攻略大全以及下载指南

植物大战僵尸杂交版自推出以来&#xff0c;以其独特的植物组合和策略玩法&#xff0c;迅速赢得了玩家们的喜爱。如果你正准备加入这场植物与僵尸的战斗&#xff0c;或者已经在战斗中寻求突破&#xff0c;那么这份保姆级的攻略大全将是你的得力助手。同时&#xff0c;我们也提供…

PLL和CDR的内部结构及其区别

比较PLL和CDR的内部结构及其区别&#xff1a; 基本结构&#xff1a; PLL&#xff08;相位锁定环&#xff09;&#xff1a; 相位检测器环路滤波器压控振荡器&#xff08;VCO&#xff09;分频器&#xff08;可选&#xff0c;用于频率合成&#xff09; CDR&#xff08;时钟数据恢复…

complex复数库学习

此头文件是数值库的一部分。本篇介绍complex的基本用法。 常用的API如下&#xff1a; 运算 real 返回实部 (函数模板) imag 返回虚部 (函数模板) abs(std::complex) 返回复数的模 (函数模板) arg 返回辐角 (函数模板) norm 返回模(范数)的平方 (函数模板) conj 返回复共轭 (函…

GuLi商城-商品服务-API-品牌管理-效果优化与快速显示开关

<template><div class"mod-config"><el-form :inline"true" :model"dataForm" keyup.enter.native"getDataList()"><el-form-item><el-input v-model"dataForm.key" placeholder"参数名&qu…

首个“可控”人物视频生成大模型--商汤Vimi:一张照片生成一分钟视频

商汤科技又整大活了&#xff0c;只需一张照片就能生成一分钟视频&#xff01; 7月4日&#xff0c;商汤发布了业内首个面向C端用户的、“可控”人物视频生成大模型产品Vimi&#xff0c;毫不夸张的说&#xff0c;视频制作者的福音来了&#xff01; Vimi有什么特别之处&#xff1…

Python爬虫零基础实战,简洁实用!

1.爬虫简介 简单来讲&#xff0c;爬虫就是一个探测机器&#xff0c;它的基本操作就是模拟人的行为去各个网站溜达&#xff0c;点点按钮&#xff0c;查查数据&#xff0c;或者把看到的信息背回来。就像一只虫子在一幢楼里不知疲倦地爬来爬去。 你可以简单地想象&#xff1a;每个…

Ubuntu 22.04 安装中文字体

笔者在用OpenCV4.9处理图片加水印时&#xff0c;中文乱码。原来是Ubuntu 22.04发行版缺少中文字体支持&#xff0c;因此&#xff0c;笔者就找资料安装了需要的中文字体&#xff0c;特此记录&#xff0c;以备后查。 1、打开终端&#xff1a; 2、更新软件包列表&#xff1a; su…

哏号分治,CF103D - Time to Raid Cowavans

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 103D - Time to Raid Cowavans 二、解题报告 1、思路分析 想了半天数据结构最终选择根号分治 我们考虑 大于 550 的公差直接暴力 小于550 的公差的所有询问&#xff0c;我们直接计算该公差后缀和&#xf…

【Linux进阶】磁盘分区3——目录树,挂载

Linux安装模式下&#xff0c;磁盘分区的选择&#xff08;极重要&#xff09; 在Windows 系统重新安装之前&#xff0c;你可能会事先考虑&#xff0c;到底系统盘C盘要有多大容量&#xff1f;而数据盘D盘又要给多大容量等&#xff0c;然后实际安装的时候&#xff0c;你会发现其实…

Rocky Linux 9.4基于官方源码制作openssh 9.8p1二进制rpm包 —— 筑梦之路

2024年7月1日&#xff0c;openssh 9.8版本发布&#xff0c;主要修复了CVE-2024-6387安全漏洞。 由于centos 7的生命周期在6月30日终止&#xff0c;因此需要逐步替换到Rocky Linux&#xff0c;后续会有更多分享关于Rocky Linux的文章。 环境说明 1. 操作系统版本 cat /etc/o…

【Odoo开源ERP】别把ERP与进销存软件混为一谈

导读&#xff1a;企业使用ERP软件能够实现管理升级&#xff0c;多方信息集成&#xff0c;按照既定策略逻辑运算&#xff0c;生成计划建议&#xff0c;减少人力成本&#xff0c;提高准确率的同时提高经营能力。 ERP&#xff0c;是MRP II的下一代软件&#xff0c;除了MRP II已有的…

(0)2024年基于财务的数据科学项目Python编程基础(Jupyter Notebooks)

目录 前言学习目标&#xff1a;学习内容&#xff1a;大纲 前言 随着数据科学的迅猛发展&#xff0c;其在财务领域的应用也日益广泛。财务数据的分析和预测对于企业的决策过程至关重要。 本专栏旨在通过Jupyter Notebooks这一强大的交互式计算工具&#xff0c;介绍基于财务的数…

Uniapp 默认demo安装到手机里启动只能看得到底tab无法看到加载内容解决方案

Uniapp 默认demo安装到手机里以后&#xff0c;启动APP只能看到底tab栏&#xff0c;无法看到每个tab页对应的内容&#xff0c;HBuilder会有一些这样的报错信息&#xff1a; Waiting to navigate to: /pages/tabBar/API/API, do not operate continuously: 解决方案&#xff1a;…

在Linux操作系统中关于逻辑卷的案例

1.如何去创建一个逻辑卷 1.1先去创建物理卷 如上图所示&#xff0c;physical volume 物理卷 被成功创建。 如上图所示&#xff0c;可以使用pvscan来去查看当前Linux操作系统的物理卷/ 1.2使用创建好的物理卷去创建一个卷组。 如上图所示&#xff0c;可以使用第一步创建的两个…