2.大闹蟠桃园【算法赛】

哈喽,大家好啊,可爱的宝子们,在讲解正文之前我们不妨来娱乐一下,不知道你们有没有看过最近非常火的一部动漫——《斩神》

今天这部分文章的开头就给大家介绍一下《斩神》中人气非常高的一位神明,她就是古希腊五位创世神之一,又被称为众神之母的黑夜女神——倪克斯.

哈哈,就让我们欣赏一下这位美丽的女神吧!

1.

2.

进入正题!

问题描述:


王母娘娘举办蟠桃会,却未邀请孙悟空。这使得孙悟空怒不可遏他当即决定大闹蟠桃园,要将蟠桃据为己有。


在蟠桃园中,有 N 条小路,编号从1到 N。这些小路构成了一个环形网络,具体来说,小路之与小路i+1(i<n)相互连接小路 N 与小路 1相互连接。每条小路都可能有天兵把守。

为了加快采摘蟠桃的速度,孙悟空施展法术,变出了N 个分身,编号从1到 N。每个分身起初皆立于其对应编号的小路上,且所采摘的蟠桃数量均为 0。每当孙悟空的本体挥动一次金箍棒,所有的分身就都会向右移动到下一条小路,并出现以下情况之一。


如果一个分身走入有天兵把守的小路,它采摘的蟠桃数量将变为 0。如果一个分身走入没有天兵把守的小路,它采摘的的蟠桃数量将增加 1。


孙悟空的本体能够任意次数地挥动金箍棒(包括0次)
请问,在多次(包括0次)挥动金棒后,所有分身所采摘的蟠桃数量之和的最大可能值是多少?

输入格式:


输入包括两行。
第一行输入一个整数 N(2 ≤ N ≤ 105),表示道路的数量,
第二行输入一个仅包含 工、Q,且长度为 N 的字符串 S,其中若S;为 工 表示道路i有天兵把守,为 Q 表示道路讠没有天兵把守(数据保证至少有1条道路有天兵把守)。

输出格式:


输出一个整数,代表所有分身采摘蟠桃数量之和的最大可能值。

样例输入:

3

L Q L

样例输出:

1

解题思路:

为了更好地理解并解决这个问题,我们可以通过一些巧妙的定义和方法来简化问题的求解过程。首先,我们不需要单独记录每个分身在每个时刻的采摘数量,而是引入一个新的变量c[i],表示当前位于小路i的分身的采摘数量。

定义c[i]:

c[i]表示当前在小路i上的分身的采摘数量。这样一来,无论什么时候挥动金箍棒,每个采摘数量都会与某个小路关联,而不是与个特定的分身关联。

定义left[i]:

接下来,为了进一步简化问题,对于每个小路i,我们定义left[i]为从小路i向左最近的有天兵把守的小路的距离特别地,如果小路i上有天兵把守,left[i]=0

推导过程:

1. 初始状态:

在初始时刻,每个小路i上的分身采摘数量为c[i],且所有分身的初始采摘数量均为0

2. 移动分析:

每次挥动金箍棒,所有分身都会向右移动一条小路。我们关心的是分身在移动过程中遇到的天兵把守的情况。

3. 采摘数量的限制:

由于left[i]表示从小路i向左最近的有天兵把守的小路的距离,因此对于任何时刻,c[i]的最大值为left[i]。这是为移动过程中,分身在遇到有天兵把守的小路之前,最多移动了left[i]。因此,c[i]的最大值为left[i].

4. 最大采摘数量的实现:

如果我们挥动金箍棒至少left[i]次,那么可以保证c[i]达到left[i]。在最多挥动N-1后,c[i]将会达到left[i]的最大值。

5. 结果求解:

综上所述,最终所有分身的采摘数量之和的最大可能值为所有left[i]的总和,∑μ1left[i]

在具体实现时,我们无需去真正地去定义c[]数组和left[]数组,而是可以从前往后遍历每一条小路,维护一个变量c来计算连续的、没有天兵把守的小路的长度,并根据求和公式2来计算 N1left[i]。这点大家应该还挺好理解的。

时间复杂度为O(N)

程序如下:

#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)
//解决VS_2022中scanf返回值被忽略的问题
/*#include<bits/stdc++.h>_VS默认情况下并不支持 stdc++.h 这个头文件,
所以我们采用如下头文件来编译运行代码*/
//考虑到大家对这些头文件比较陌生,所以我们来详解一下这些头文件
#include <iostream>
/*#include <iostream> 是C++程序中非常常见的一条预处理指令,它包含了iostream库。
iostream库提供了C++程序中用于处理标准输入/输出流的基本功能。
这个库中定义了一些重要的类和对象,以及与输入/输出相关的函数。
以下是iostream库中的一些关键组件:

std::istream 类:这是一个输入流类,用于从输入设备(如键盘、文件等)读取数据。

std::ostream 类:这是一个输出流类,用于向输出设备(如屏幕、文件等)写入数据。

std::cin 对象:这是一个std::istream类型的对象,表示标准输入流(通常是键盘输入)。
它是std::istream类的一个实例。

std::cout 对象:这是一个std::ostream类型的对象,表示标准输出流(通常是屏幕输出)。
它是std::ostream类的一个实例。

std::cerr 对象:这是一个std::ostream类型的对象,表示标准错误流。
它通常用于输出错误消息。
与std::cout相比,std::cerr默认情况下是非缓冲的,这意味着错误消息会立即显示,而不是等待缓冲区被填满。

std::clog 对象:这是一个std::ostream类型的对象,表示标准日志流。
它与std::cerr类似,但用于输出日志消息。

除了这些基本组件之外,iostream库还包括了其他与流处理相关的类,
例如std::stringstream、std::ifstream和std::ofstream等。
这些类分别用于处理字符串流、文件输入流和文件输出流。*/
#include <vector>
/*
(1)在C++中,vector是一种使用非常广泛的容器类,属于标准模板库(STL)的一部分。
它能够存储任意类型的对象,从基本类型如int、float到自定义类型都可以。
更重要的是,vector支持动态扩展,不需要程序员手动管理内存,极大地提高了编程效率和安全性。
(2)vector是变长数组,支持随机访问,不支持在任意位置O(1)插入。为了保证效率,元素的增删一般应该在末尾进行。
(3)在C++的标准模板库(STL)中,vector是一个非常有用的动态数组容器。它允许我们存储可变大小的同类型元素序列,
并且能够动态地增长和缩小。由于其灵活性和易用性,vector在C++编程中得到了广泛的应用。
*/
#include <algorithm>
/*
#include <algorithm> 是C++中一个常用的预处理指令,它包含了algorithm库。
这个库提供了大量用于操作序列(例如数组、向量、列表等容器)的通用算法,这些算法包括查找、排序、复制、移动、修改和其他操作。
以下是algorithm库中一些常用函数接口的概述:

std::sort(begin, end):对序列进行排序。begin和end是序列的起始和结束迭代器。

std::stable_sort(begin, end):对序列进行稳定排序(保持相等元素的相对顺序)。

std::reverse(begin, end):反转序列中的元素顺序。

std::find(begin, end, value):查找序列中第一个等于value的元素。如果找到,返回指向该元素的迭代器,否则返回end。

std::count(begin, end, value):计算序列中等于value的元素个数。

std::min_element(begin, end):查找序列中的最小元素。返回指向最小元素的迭代器。

std::max_element(begin, end):查找序列中的最大元素。返回指向最大元素的迭代器。

std::copy(source_begin, source_end, dest_begin):从源序列复制元素到目标序列。返回指向目标序列末尾的迭代器。

std::move(source_begin, source_end, dest_begin):将源序列的元素移动到目标序列。

std::remove(begin, end, value):移除序列中所有等于value的元素。返回指向新序列末尾的迭代器。

std::unique(begin, end):移除序列中所有连续重复的元素。返回指向新序列末尾的迭代器。

std::replace(begin, end, old_value, new_value):将序列中所有等于old_value的元素替换为new_value。

std::fill(begin, end, value):将序列中的所有元素设置为value。

std::for_each(begin, end, function):对序列中的每个元素应用function。

这只是algorithm库中众多函数的一部分。在实际编程中,这个库为处理序列数据提供了非常强大的功能。
使用这些通用算法可以简化代码,提高代码的可读性和可维护性。
*/
using namespace std;//命名空间
int main() {
	//对用户输入的一串字符进行处理;
	int N; cin >> N;//声明整型变量N,用于接收用户输入的一个整数
	vector<int>A(N);//使用cin从标准输入读取N并动态创建一个大小为N的vector<int类型的数组A;
	for (int i = 0; i < N; i++) {//for循环;遍历范围从0~N-1;
		char x;
		cin >> x;
		if (x == 'L') A[i] = 0;
		else A[i] = 1;
	}
	//用于将向量A中第一个遇到的0元素移动到最前面的位置,然后终止循环
	for (int i = 0; i < N; i++) {//for循环;遍历整型向量A中的元素
		if (A[i] == 0) {//调用std::rotaate
			rotate(A.begin(), A.begin() + i + 1, A.end());//由i+1开始到向量结尾的所有元素向前移动一位,使得原本在i处的0元素移动到向量的最前面
			break;//找到并移动了第一个0,跳出循环
		}
	}
	//用于计算给定数组A中连续为1的子段之间的空0元素的数量
	long long c = 0, ans = 0;
	/*long long c=0 长整型变量;用于记录遇到的第一个1之前连续的0的个数;
	  long long ans=0 用于存储最终结果*/
	for (int i = 0; i < N; i++) {//for循环,遍历数组A的每个元素,从索引i = 0到N - 1
		if (A[i] == 0) {
			ans += c * (c + 1) / 2;//组合公式计算
			c = 0;
		}
		if (A[i] == 1) c++;
	}
	//循环结束
	cout << ans << '\n';//ans包含了所有有效空0元素的序列和,最后通过cout将其输出,并返回0表示程序正常结束。
	return 0;
}

运行结果:

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当孙悟空吃蟠桃时,华为OD可能会通过其技术和产品提供支持与帮助。 首先,华为OD是华为的开放开发平台,为开发者和合作伙伴提供了丰富的技术资源和开发工具。在孙悟空吃蟠桃的场景下,华为OD可能会提供一种基于物联网技术的智能食品追溯系统。这个系统可以追踪蟠桃的种植、采摘、存储、运输等环节的信息,确保蟠桃的安全和品质。开发者可以通过华为OD平台的技术资源和工具,以及与华为合作伙伴的协作,构建这样一个智能食品追溯系统。 其次,华为OD平台可能还提供一些与孙悟空吃蟠桃相关的应用程序。比如,一个基于华为OD平台的智能家居应用,可以通过识别孙悟空的声音或人脸,自动提供一些便利的功能。比如,当孙悟空靠近蟠桃时,系统可以自动将蟠桃洗净或剥皮,或者提供一些有关蟠桃的健康食谱推荐。 最后,华为OD平台还可能提供一些与蟠桃相关的社交媒体应用。可以想象,孙悟空吃蟠桃的场景会引起很多人的兴趣和关注,人们可能愿意分享自己的蟠桃经历、菜谱或者与孙悟空的互动等。华为OD平台可以提供一个社交媒体平台,让用户可以方便地分享和交流这些有趣的内容。 总之,华为OD可能会通过技术支持、应用开发和社交媒体等方面,为孙悟空吃蟠桃这个场景提供多样化的解决方案和体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值