B. Array Walk(贪心)

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();
	} 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值