CF413C Jeopardy!
题意翻译
题意简述
“Jeopardy!”的决赛将有n问题,每个问题都有对应的得分ai,其中有m个问题可以选择不得分,而将现有总得分翻倍。你可以安排关卡的通过顺序和策略,求最大得分。
输入输出格式
输入格式:
第一行包含两个整数。n和m(1<=n,m<=100;m<=min(n,30))分别代表问题总数和可翻倍问题总数。第二行包含n个整数a1,a2,...,an(1<=ai<=1e7)代表每个问题的价值;第三行包含m个整数b1,b2,...,bm(1<=bi<=n)代表可翻倍问题的编号。问题编号是从1到n。
输出格式:
一行一个数字,表示通过所有关卡最大得分。保证该答案在64位带符号整型范围内。
感谢@Peter_Matthew 提供的翻译
题解:
贪心题。
对于那些不能翻倍的直接加一起。
对于能翻倍的,肯定要考虑翻不翻倍对答案的贡献哪个大。
那么,发现大的翻倍肯定更大,所以在排序的过程中,把所有能翻倍的按权值从大到小排序。然后从大到小依次判断到底要不要翻倍。这样的决策一定是最优的。
所以这题在考结构体排序
代码:
#include<bits/stdc++.h>
using namespace std;
int n, m;
long long ans;
struct node
{
int val;
bool f;
bool operator < (const node &a) const {
return f < a.f || (f == a.f && val > a.val);
}
}a[220];
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; ++i)
cin >> a[i].val, a[i].f = 0;
for (int i = 1; i <= m; ++i)
{
int x;
scanf("%d", &x);
a[x].f = 1;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i)
{
if (!a[i].f)
ans = ans + a[i].val;
else
{
if (ans > a[i].val) ans *= 2;
else ans = ans + a[i].val;
}
}
printf("%lld
",ans);
return 0;
}