长话短说,简明扼要一直是我的行事风格,如有不精准的地方,就到网上去搜,好吧。
今天分享我们做的四道题,都挺简单的,就是难思考。
1.Maximum Subarray Sum
2.分解因数
3.公交换乘
4.Vacation
我们先来看一下第一道题。
我们先看一下题目,把英文翻译成中文就是“最大子数组和”。结合这个再看一下题面:
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;
}
尽量手写,不要复制,可以加强对代码的理解。
这个没什么难度吧。跑一下样例:
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;
}
这里样例解释,和思路都有了,我们就设置一个结构体,把时间,花费,和是公交车还是地铁,存起来。
代码如下:
// 公交换乘
#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;
}
最后一个题:
题目够简单了吧。
这里涉及了一个知识点:
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;
}
谢谢大家观看。