一、游游的水果大礼包
题目解析

现在有
n
个苹果、m
个桃子,我们现在可以将2
个苹果和1
个桃子组成一号大礼包 ;1
个苹果和2
个桃子组成二号大礼包一号大礼包 的价值为
a
、二号大礼包 的价值为b
。要我们求出来,我们可以组合出来的礼包的最大价值。
算法思路
本道题,正确的解法是枚举:
题目给了
n
个苹果,m
个桃子;那我们就枚举出来所有的情况(组合一号礼包
0
个到组合一号礼包最多个 ),这样我们一号礼包的个数的区间为[0 , x]
;那这个
x
怎么去求呢?(这算是本道题第一个坑 ,博主在第一次做时就将max
求错了导致这道题没有通过)(先继续往下看)在我们枚举
一号礼包
和二号礼包
的数量时,我们要求的价值就等于count1*a + count2*b
。在遍历的过程中,更新结果即可。
现在来看这里比较重要的点
- 一号礼包个数区间
[0 , x]
中的x
如何去求? :这里我们不仅要考虑苹果是数量n
,也要考虑桃子的数量m
;那max
就应该等于苹果能组成一号礼包的数量n/2
和桃子能够组成一号礼包的数量m
的最小值,即x = min(n/2 , m)
。- 还用一个要注意的点,就是数据的范围 ,题目中给定
n,m,a,b
的范围是[1 , 1000000]
;那这样我们最终结果使用int
肯定是不行的,要使用long long
类型。
这里,如果想要使用贪心算法进行优化是行不通的,题目中给的条件太少了,这里就不讲解使用贪心
优化了。
代码实现
cpp
#include<iostream>
using namespace std;
int main()
{
int n,m,a,b;
cin>>n>>m>>a>>b;
int t = min(n/2,m);
long long ret = 0;
for(int x = 0;x<=t;x++)
{
long long y = min(n - 2*x,(m - x)/2);
ret = max(ret , x*a + y*b);
}
cout<<ret<<endl;
return 0;
}
二、买卖股票的最好时机(二)
题目解析

昨天的是买卖股票的最好时机(一),现在(二)来了。
现在来看题,还是给定一个数组
paices
,表示每一天股票的价格,我们现在要根据这个价格表paices
返回买卖股票的最大利益和上道题目不同的是
- 我们可以多次买卖股票,但是再次购买股票之前,必须卖出之前的股票(简单来说就是,我们手中最多只能存在一种股票)
- 如果没有收益,就返回
0
- 买卖股票没有手续费(就是没有损耗)
算法思路
这道题,算法思路就是贪心
(那我没有学过贪心怎么办?不要慌,博主也只是听说过贪心而已)
现在来看整体思路:
在这道题中,我们可以多次买卖股票,所以我们不管三七二十一,直接买入股票,如果后面股票价格要高于我们买入的价格,那就卖出赚取利润;如果不高于我们买入的价格,那就当天买当天卖嘛,反正有没有亏损。
其实整道题的思路就是上述买卖股票的方法,那转化成我们代码,该如何理解呢?
- 从左往右遍历数组
paices
, 表示我们买卖股票的整个过程- 遍历到
i
位置时,就表示在第i
天买入股票- 我们定义
j
,让j
从i+1
位置开始向后遍历,如果paices[j] <= paices[j-1]
(就表示卖出的价格不高于买入的价格/股票在降价
,那我们就要早点卖出了,就当天买当天卖,没有利润 );如果paices[j] > paices[j-1]
(就表示当前股票价格在上涨,我们先不买,找到股票的最高价格再卖出)。j
遍历结束后,将j
的值赋给i
,让i
从j
位置再遍历数组paices
。
整体思路如上,我们现在来梳理一下整个过程,帮助理解
首先输入数据,存到
paices
中定义
i
从左往右遍历paices
,再定义j
,从i+1
位置开始向后遍历数组,遇到paices[j] <= paices[j-1]
就让j
结束遍历,遇到paices[j] >paices[j-1]
就继续往后遍历。
j
遍历结束后,更新结果,并把j
的值赋给i
。
代码实现
cpp
#include <iostream>
#include<vector>
using namespace std;
int main() {
int n;
cin>>n;
vector<int> paices(n);
for(int i=0;i<n;i++)
{
cin>>paices[i];
}
int ret =0;
for(int i =0;i<n;)
{
int j = i+1;
while(j<n && paices[j]>paices[j-1])
{
j++;
}
ret += (paices[j-1] -paices[i]);
i = j;
}
cout<<ret<<endl;
return 0;
}
三、倒置字符串
题目解析

它们给定我们应该字符串,让我们将其中的单词倒置,但是标点符号不倒置。
例如
I like beijing.
经过倒置后变成了beijing. like I
。
算法思路
对于这道题,它只是让我们将其中的单词逆置,如果我们直接去逆置那可以是非常非常难了。
这里来看思路一:
- 先将整个字符串进行逆置(
I like beijing.
->.ginjieb ekil I
)- 然后再遍历字符串,找到每一个单词并进行逆置。(
.ginjieb ekil I
->beijing. like I
)对于这种思路呢,我们写起来不是很麻烦,但要注意:
我们要使用
getline
来读取一行。这里单词直接以隔开,找单词的时候就要以 为找到标准。
这里再来看一种思路:
我们使用
cin
,它读取到是读取结束的,那我们使用
cin
读取一次的结果就是一个单词;这样我们依次读取每一个单词,将它放到数组中,最后逆置一下数组,这样就得到了倒置后单词的一个数组。这样我们依次输出,并以
隔开即可。
代码实现
这里就只实现第二种思路了,感兴趣可以去实践一下思路一
cpp
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
int main() {
string str;
vector<string> vs;
while(cin>>str)
{
vs.push_back(str);
}
reverse(vs.begin(),vs.end());
for(auto& e:vs)
{
cout<<e<<' ';
}
cout<<endl;
return 0;
}
到这里,今日刷题就结束了,感谢各位的支持。
继续加油!!!