Problem - 1389B - Codeforces
给你一个数组a1,a2,...,an,由n个正整数组成。
最初,你站在索引1处,分数等于a1。你可以进行两种移动。
向右移动--从你当前的索引x走到x+1,并将ax+1加入你的分数。这个动作只有在x<n时才能进行。
向左移动 - 从你当前的索引x到x-1,并将ax-1加入你的分数。这步棋只有在x>1时才能进行。此外,你不能连续执行两个或更多的向左移动。
你要正好执行k步棋。另外,其中向左移动的次数不应超过z次。
你能达到的最高分数是多少?
输入
第一行包含一个整数t(1≤t≤104)--测试案例的数量。
每个测试案例的第一行包含三个整数n,k和z(2≤n≤105, 1≤k≤n-1, 0≤z≤min(5,k))--数组中的元素数,你应该执行的总步数和你可以执行的最大向左步数。
每个测试案例的第二行包含n个整数a1,a2,...,an(1≤ai≤104)--给定的数组。
所有测试案例的n之和不超过3⋅105。
输出
打印t个整数--对于每个测试案例,如果你总共走了k步棋,其中不超过z步棋是向左的,并且没有两步或更多步棋是向左的,则输出你能达到的最大分数。
例子
输入复制
4
5 4 0
1 5 4 3 2
5 4 1
1 5 4 3 2
5 4 4
10 20 30 40 50
10 7 3
4 6 8 2 9 9 7 4 10 9
输出拷贝
15
19
150
56
注意
在第一个测试案例中,你根本不允许向左移动。所以你向右走了四步,得到的分数是a1+a2+a3+a4+a5。
在第二个例子中,你可以向左移动一次。所以我们可以按照这些动作:右、右、左、右。得分将是a1+a2+a3+a2+a3。
在第三个例子中,你可以向左移动四次,但无论如何这都不是最佳选择,你可以直接向右移动四次,得到的分数是a1+a2+a3+a4+a5。
题解:
dp不会写,我们想想贪心的策略
如果z为0,我们只能往右走选k个不需要讨论
如果我们可以往左走,那么我们应该在相加最大的两个上反复走,所以直接枚举所有相邻两个找最大即可
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
#define int long long
typedef pair<int,int> PII;
int a[200050];
void solve()
{
int n,k,z;
cin >> n >> k >> z;
for(int i = 1;i <= n;i++)
cin >> a[i];
int ans = 0,sum = 0,mx = 0;
k++;
for(int i = 1;i <= k;i++)
{
sum += a[i];
if(i < n)
mx = max(mx,a[i] + a[i+1]);
ans = max(ans,min((k-i)/2,z)*mx+sum);
}
cout << ans<<"\n";
}
//1 2 3 4 5
//
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}