c++2024寒假J312实战班2.4

长话短说,简明扼要一直是我的行事风格,如有不精准的地方,就到网上去搜,好吧。

今天分享我们做的四道题,都挺简单的,就是难思考。

题目列表:

        1.Maximum Subarray Sum

                2.分解因数

                        3.公交换乘

                                4.Vacation

我们先来看一下第一道题。

Maximum Subarray Sum

        我们先看一下题目,把英文翻译成中文就是“最大子数组和”。结合这个再看一下题面:

Given an array of n integers, your task is to find the maximum sum of values in a contiguous, nonempty subarray.

意思就是:

给定一个包含n个整数的数组,计算连续非空子数组元素和的最大值。

我们再来理解一下这段话:
比如输入:

8 (n个数据)
-1 3 -2 5 3 -5 2 2 (每个元素的值,一共n个元素)

输出:

9

        问什么,我们来看一下,最长的应该是第2个(3),到第5个(3)。加起来就是3+-2+5+3 = 9。问什么后面的不算呢,因为|-5| 和 2 + 2 = 4,那个大? 肯定 |-5| 更大呀,所以最后的答案一定小于0,就会产生反向效益让答案减小

我门就有这样的解题思路:
以 这个元素 结尾连续子序列最大和。如果将 这个元素 加入之前子序列和能够使得和更大,就将 这个元素 加入;否则重新开始一个新的子序列

我们就看一下答案:

//Maximum Subarray Sum
#include 
using namespace std;
typedef long long LL;
int main() {
    int n;
    cin >> n;
    vector A(n);
    for (LL &a : A) cin >> a;
    LL d = A[0], maxd = d;
    for(int i = 1; i < n ; i++)
        d = max(A[i], d + A[i]), maxd = max(maxd, d);  
    cout << maxd << '\n';
    return 0;
}

尽量手写,不要复制,可以加强对代码的理解。

分解因数

c++2024寒假J312实战班2.4_第1张图片

这个没什么难度吧。跑一下样例:
2有2一个(因为1不算),20有2*10,2*2*5,4*5,20,4种。

// 分解因数
#include 
#include 
#include 
using namespace std;
typedef long long LL;
vector F;
LL dfs (int k, int a){
    if (a == 1) return 1; //如果a = 1了是不是就找到一种方案了
    LL ans = 0;
    for (int i = k, sz = F.size(); i < sz; i++)
        if (a % F[i] == 0) ans += dfs(i, a / F[i]); //递归求解
    return ans;
}
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0, a; i < n; i++){
        cin >> a, F.clear(); // 输入,并清空
        for (int j = 2; j <= a; j++)
            if (a % j == 0) F.push_back(j);// 因数
        printf ("%lld\n", dfs (0, a));
    }
    return 0; 
}

 公交换乘

c++2024寒假J312实战班2.4_第2张图片

 

这里样例解释,和思路都有了,我们就设置一个结构体,把时间,花费,和是公交车还是地铁,存起来。

代码如下:

// 公交换乘
#include 
using namespace std;
struct Item {
  int a;            // 0代表地铁,1代表公交车
  int price, time;  // 票价, 时间
};
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n;
  cin >> n;
  Item it;
  list s;  // 地铁票,按照时间递增排序, 相当于队列,底层是双向链表
  int ans = 0;
  for (int i = 0; i < n; i++) {
    cin >> it.a >> it.price >> it.time;  // 输入一条新的记录
    if (it.a == 0) {                     // 地铁
      ans += it.price, s.push_back(it);
      continue;
    }                    // 下面考虑公交
    auto p = s.begin();  // 过期的地铁票要全部删除
    while (p != end(s) && it.time - p->time > 45) p = s.erase(p);
    while (p != end(s) && p->price < it.price) p++;  // 跳过金额不够的优惠券
    if (p != end(s))  // p就指向一张优惠券,可以乘车的
      s.erase(p);  // 用一张优惠票乘车并且删除(链表可以在中间删除)
    else
      ans += it.price;  // 只能掏钱了
    }
    printf("%d\n", ans);
    return 0;
}

最后一个题:

 Vacation

c++2024寒假J312实战班2.4_第3张图片

题目够简单了吧。

这里涉及了一个知识点:

max(a , b)这是不是原来的写法,我可以改成这样:max({a,b,c,d,e,f··········})。自己玩儿一下。

 

// Vacation
#include 
using namespace std;
typedef long long LL;
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n;
  cin >> n;
  vector> D(n + 1, vector(3, 0));
  // D[i,j]: 第i天活动为j,[1...i]天对应的答案
  for (int i = 1; i <= n; i++)
    for (int j = 0, a; j < 3; j++) {  // 第i天为活动为j
      cin >> a;
      for (int lj = 0; lj < 3; lj++)  // 第i-1天为lj
        if (lj != j) D[i][j] = max(D[i][j], D[i - 1][lj] + a);
    }
  return printf("%lld\n", max({D[n][0], D[n][1], D[n][2]})), 0;
}

谢谢大家观看。

你可能感兴趣的:(c++,算法)