第五周任务 [Cloned] - Virtual Judge (vjudge.net)
【题目描述】
你的朋友送了你一个排队作为生日礼物。D
D是一个水平圆柱体,包含一排珠宝。N
珠宝的价值从左到右。可能有负值的珠宝。V1,V2,...,VN
一开始,你手中没有宝石。
大多数时间(可能为零次)可以对 执行大多数操作,从以下选项中选择:
-
操作A:取出最左边的宝石,拿在手里。当为空时,无法执行此操作。D
-
操作B:取出里面最右边的宝石,拿在手里。当为空时,无法执行此操作。D
-
操作C:选择手中的宝石,将其插入。当您手中没有宝石时,您无法执行此操作。D
-
操作D:选择手中的宝石,将其插入。当您手中没有宝石时,您无法执行此操作。D
在操作后找到您手中珠宝价值的最大可能总和。
【输入】
- 输入中的所有值都是整数。
- 1≤N≤50
- 1≤K≤100
- −107≤Vi≤107
【输出】
操作后打印手中珠宝价值的最大可能总和。
解题思路
题意大概是:在有限的操作下,拿在手上的珠宝价值最大。
要注意的是,手上不止可以拿一个珠宝,可以拿多个,要拿到最大价值的珠宝,主要是操作数的限制。
此处用到优先队列,可以很迅速地解决问题。
用两层循环,遍历左端和右端的操作数,第一层循环是拿左端的珠宝用的操作数,第二层循环是拿右边的珠宝用的操作数,接着就是根据操作数取走珠宝,内部用循环将珠宝放入优先队列中。
接着看是否存在剩余操作数k,剩余操作数k可以用掉作为把珠宝放回,或者是不放回去,因为此时手中的珠宝价值都大于零了。这里要用的while循环,要考虑队列的长度,剩余操作数,还有手中最小价值的珠宝是否大于零。
接着将队列中的元素累加并出队,并与ans比较,sum>ans,就将ans赋为sum。
数据范围不大,可以用int存储。
代码如下
#include<iostream>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
int n, m;
ll a[105];
priority_queue<ll, vector<ll>, greater<ll> >s;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
ll ans = 0;
for (int i = 0; i <= m; i++) {
for (int j = 0; (i + j) <= min(n, m); j++) {
for (int q = 1; q <= i; q++)
s.push(a[q]);
for (int q = n; q >=n-j+1; q--)
s.push(a[q]);
int k = m - i - j;
while (s.size() && s.top() < 0 && k){
s.pop();
k--;
}
ll sum = 0;
while (s.size()){
sum += s.top();
s.pop();
}
ans = max(sum, ans);
}
}
cout << ans << endl;
return 0;
}