c++贪心 二零二零

给出一个字符串S,其中满足S的每一个字符都是数字字符,你要删除S的连续一段字符(也可以删除0个字符),使得剩下的字符依次连接起来的字符串是“2020”,可以做到吗?如果可以做到输出“YES”,否则输出“NO”。

输入格式

第一行,一个整数G,表示有G组测试测试。1<=G<=10。

每组测试格式如下:

第一行,一个整数n,表示字符串S的长度。1<=n<=200。

第二行,字符串S。

输出格式

共G行,每行一个字符串,“YES”或“NO”,双引号不用输出。

输入/输出例子1

输入:

5

8

20192020

8

22019020

4

2020

5

20002

6

729040

输出:

YES

YES

YES

NO

NO

样例解释

#include<bits/stdc++.h>
using namespace std;
int G,n,len;
string s;
bool cheak(string s)
{
    len=s.size();
    if(s[0]=='2'&&s[len-3]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
    if(s[0]=='2'&&s[1]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
    if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[len-1]=='0')return true;
    if(s[len-4]=='2'&&s[len-3]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
    if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[3]=='0')return true;
    return false;
}
int main()
{
    cin>>G;
    while(G--)
    {
        cin>>n;
        cin>>s;
        if(cheak(s)==true)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    
    return 0;
}

<think>嗯,用户想了解C++中的贪心算法。好的,首先我得回忆一下贪心算法的基本概念。贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致全局最优解的算法策略。不过,贪心算法并不总是能得到全局最优解,只有在问题满足贪心选择性质的时候才能有效。 那用户可能想知道如何在C++中实现贪心算法,或者常见的应用场景。首先,我需要解释贪心算法的核心思想,然后给出具体的例子。比如,活动选择问题、找零钱问题、霍夫曼编码等,这些都是经典的贪心算法应用案例。 接下来,可能需要详细说明贪心算法的步骤:首先,将问题分解为若干子问题,每个子问题都有一个最优解;然后,确定每一步的局部最优选择;最后,将这些局部最优解组合起来,形成全局解。需要注意的是,必须验证问题是否适合贪心算法,否则可能得到错误的结果。 然后,在C++中实现贪心算法,通常会涉及到排序、优先队列等数据结构。例如,活动选择问题需要按照结束时间排序,然后依次选择不冲突的活动。这时候需要给出具体的代码示例,比如排序后遍历活动的过程。 不过,用户可能对代码的正确性和效率感兴趣。需要强调贪心算法的适用条件,比如活动选择问题中,选择结束时间最早的活动能够最大化剩余时间,从而得到最优解。同时,要指出贪心算法的局限性,例如部分背包问题可以使用贪心,而0-1背包问题则不行。 另外,可能需要比较动态规划和贪心算法的区别,贪心的优势在于高效,但可能无法得到最优解。这时候举例子说明,比如硬币找零问题,如果硬币面额是标准的1、5、10等,贪心可行,但如果面额不同,比如1、3、4,要找6元的话,贪心选4+1+1不如3+3更优,这时候就需要动态规划了。 在代码实现部分,可以给出一个找零的例子,使用贪心策略,从大到小选择硬币。例如,用C++的vector存储硬币面额,然后循环减去最大可能的硬币值,记录硬币数量。 同时,需要提醒读者,在实际应用中要验证问题是否满足贪心条件,避免错误。例如,在最小生成树的Prim算法和Kruskal算法中,贪心策略有效,但需要正确实现。 可能用户还有疑问,如何判断一个问题是否适合贪心算法。这时候需要解释贪心选择性质和最优子结构。贪心选择性质指的是通过局部最优选择能够达到全局最优;最优子结构指的是问题的最优解包含子问题的最优解。 总结一下,回答的结构应该是先介绍概念,然后步骤,接着应用场景,再给出C++的代码示例,并讨论适用条件和注意事项。最后比较其他算法,强调优缺点。 现在,需要确保回答符合系统级指令:行内数学公式用$...$,独立公式用$$...$$,正确使用LaTeX语法。例如,在活动选择问题中,可能涉及到数学表达式,比如活动的开始和结束时间满足$s_i < f_i$,或者最优解的结构分析。 在代码部分,需要用C++的语法高亮,比如: ```cpp #include <vector> #include <algorithm> using namespace std; int greedyCoinChange(int amount, vector<int>& coins) { sort(coins.rbegin(), coins.rend()); // 降序排序 int count = 0; for (int coin : coins) { while (amount >= coin) { amount -= coin; count++; } } return amount == 0 ? count : -1; } ``` 然后解释这段代码的逻辑,排序硬币面额,从大到小,尽可能多地使用大面额硬币。 最后,还要提醒用户贪心的局限性,以及何时使用动态规划或其他方法。例如,如果硬币面额是1、3、4,找6元时,贪心给出的是4+1+1(3枚),而最优解是3+3(2枚),这时候需要动态规划来处理。 这样,整个回答结构清晰,逐步引导用户理解贪心算法C++中的应用,同时注意正确性和实际应用中的问题。</think>### C++贪心算法分步解析 贪心算法是一种**通过局部最优选择推导全局最优解**的算法策略。以下从核心概念到具体实现分步骤说明: --- #### 一、核心特征 1. **贪心选择性质** 每一步选择当前最优解($局部最优$),且该选择不影响后续决策 2. **最优子结构** 全局最优解包含子问题的最优解(数学证明常用归纳法) --- #### 二、典型应用场景 | 问题类型 | 贪心策略 | 时间复杂度 | |---------|---------|-----------| | 活动选择问题 | 选结束最早的活动 | $O(n \log n)$ | | 霍夫曼编码 | 合并频率最低的节点 | $O(n \log n)$ | | 最小生成树 | Prim/Kruskal算法 | $O(E \log V)$ | | 硬币找零问题 | 优先用大面额硬币 | $O(n)$ | --- #### 三、C++实现步骤(以找零问题为例) 1. **问题描述** 给定金额$amount$和硬币面额数组$coins$,求最少硬币数 2. **算法验证** 当硬币面额满足$coins = [1, 5, 10, 25]$时成立(标准美分系统) 3. **代码实现** ```cpp #include <vector> #include <algorithm> int greedyChange(int amount, std::vector<int>& coins) { std::sort(coins.rbegin(), coins.rend()); // 降序排序 int count = 0; for (int coin : coins) { if (amount <= 0) break; count += amount / coin; // 取最大可用数量 amount %= coin; // 更新剩余金额 } return (amount == 0) ? count : -1; } ``` 4. **执行流程示例** - 输入:amount = 63,coins = [1, 5, 10, 25] - 计算步骤: 25×2 → 10×1 → 5×0 → 1×3 → 总硬币数 = 2+1+3 = 6 --- #### 四、注意事项 1. **反例警示** 当硬币面额为[1, 3, 4]时,求找零6元: - 贪心结果:4+1+1=3枚 - 实际最优:3+3=2枚 **此时需用动态规划** 2. **适用性判断** 必须严格证明两个核心特征,常见验证方法: - 替换法:假设存在更优解,推导矛盾 - 数学归纳法:证明各步骤选择的正确性 --- #### 五、对比其他算法 | 算法类型 | 优点 | 缺点 | 典型问题 | |---------|------|------|---------| | 贪心算法 | 高效简单 | 不保证全局最优 | 最小生成树 | | 动态规划 | 保证最优解 | 高时空复杂度 | 0-1背包问题 | | 分治算法 | 结构清晰 | 子问题需独立 | 归并排序 | --- ### 扩展练习 尝试用贪心算法解决以下问题: 1. **区间调度问题** 给定$n$个会议时间区间,求最多能参加的会议数 **提示**:按结束时间排序 2. **跳跃游戏** 数组每个元素表示最大跳跃长度,判断能否到达终点 **提示**:维护当前能到达的最远位置 通过具体代码实现加深对贪心策略的理解,并注意验证算法的正确性边界条件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值