能量石(贪心+背包)
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了能量石(贪心+背包)相关的知识,希望对你有一定的参考价值。
题目链接
题意:
怪物要吃能量石,每个能量石有个初始能量 E i E_i Ei,但是随着时间的消耗会不断减少,每个能量石有一个固定的减少速度 L i L_i Li,怪物吃能量石有一定的时间消耗,吃每个能量石的时间为 S i S_i Si,求能够获得的最大能量。
思路:
先贪心:
吃能量石有不同的顺序,每个顺序得到的最大值也不同,所以我们要贪心求出来一个能够获得最大值的顺序,然后通过这个顺序求最大值
因为要求获得的最大能量,对第 i i i位和第 i + 1 i+1 i+1位进行进行数学式子的表达:
- 交换前:
位置 | 获得能量 |
---|---|
第 i 位 i位 i位 | E i E_i Ei |
第 i + 1 i+1 i+1位 | E i + 1 − S i ∗ L i + 1 E_{i+1}-S_i*L_{i+1} Ei+1−Si∗Li+1 |
- 交换后
位置 | 获得能量 |
---|---|
第 i i i位(此时第i+1已经交换过来了) | E i + 1 E_{i+1} Ei+1 |
第 i + 1 i+1 i+1位 | E i − S i + 1 ∗ L i E_{i}-S_{i+1}*L_{i} Ei−Si+1∗Li |
然后
E
i
+
E
i
+
1
−
S
i
∗
L
i
+
1
<
E
i
+
1
+
E
i
−
S
i
+
1
∗
L
i
E_i+E_{i+1}-S_i*L_{i+1}<E_{i+1}+E_{i}-S_{i+1}*L_{i}
Ei+Ei+1−Si∗Li+1<Ei+1+Ei−Si+1∗Li
得到
S
i
∗
L
i
+
1
<
S
i
+
1
∗
L
i
S_i*L_{i+1}<S_{i+1}*L_{i}
Si∗Li+1<Si+1∗Li
即为贪心规则,按此顺序排序就是最大值 的顺序
后面01背包:
类似01背包问题
f
[
j
]
f[j]
f[j]表示时间恰好等于
j
j
j的最大值
- 需要处理的就是对每个能力值进行变化,因为有时间消耗,初始能量 − - −吃该能量石的时间*能量消耗的速度
#include<bits/stdc++.h>
using namespace std;
const int N = 105,M=10005;
struct stone
{
int s,e,l;
bool operator < (const stone &a)const
{
return s*a.l < a.s*l;//升序排序
}
}stone[N];
int f[M];
int main()
{
int kase = 1;
int t;
cin>>t;
while(t--)
{
int n;cin>>n;
int m = 0;
for(int i=1;i<=n;i++)
{
int s,e,l;
cin>>s>>e>>l;
m+=s;
stone[i]={s,e,l};
}
sort(stone+1,stone+1+n);
memset(f,-0x3f,sizeof(f));
f[0] = 0;
for(int i=1;i<=n;i++)
{
int s = stone[i].s,e = stone[i].e,l = stone[i].l;
for(int j=m;j>=s;j--)
f[j] = max(f[j],f[j-s]+e-(j-s)*l);
}
int res = 0;
for(int i=0;i<=m;i++)
{
res = max(res,f[i]);
}
cout<<"Case #"<<kase++<<": "<<res<<'\\n';
}
}
以上是关于能量石(贪心+背包)的主要内容,如果未能解决你的问题,请参考以下文章