题意转化:
首先一共有n块石头,因为降到最小为0
我们可以视作我们这n块石头全取
那我们暂时拥有所有的能量
接下来我们再减去时间流逝的能量
那么我们就是要将流逝的能量最小化,那么我们要的能量就能最大化
分析相邻两个石头i和i+1
先选i再选i+1得到能量是$E_{i}+E_{i+1}-S_{i} \times l_{i+1}$
先选i+1再选i得到的能量是$E_ {i+1}+E_ i-S_ {i+1} \times L_i$
那么贪心的方式就是先选能量损失小的
那么就是$S_ i * l_ {i + 1} < S _ {i+1} \times L_i$
状态方程分析
01背包问题
$f[n][m]$代表选第i个物品,恰好用时m时
01背包恰好的问题,我们都会先将f数组初始化为负无穷
原因在于,即使有些状态是我们取不到的,我们也不会更新它,因为这个状态两个转移方向都是负无穷
转移方程是:
$f[j]=max(f[j],f[j-s]+e-(j-s) \times l)$
因为能量有损失,所以需要$+e-(j-s) \times l$
完结,撒花
#include<bits/stdc++.h>
using namespace std;
const int N=110,M=10010;
int f[M];
struct stone
{
int s,e,l;
bool operator<(const stone &W)
{
return s*W.l<W.s*l;
}
}a[N];
int main(){
ios::sync_with_stdio(false);
int T,n,m;
cin>>T;
for(int tt=1;tt<=T;tt++)
{
cin>>n;
m=0;
memset(f,-0x3f,sizeof f);
f[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i].s>>a[i].e>>a[i].l;
m+=a[i].s;
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i].s;j--)
f[j]=max(f[j],f[j-a[i].s]+a[i].e-a[i].l*(j-a[i].s));
}
int res=0;
for(int i=0;i<=m;i++) res=max(res,f[i]);
cout<<"Case #"<<tt<<": "<<res<<endl;
}
return 0;
}
似乎版面的符号有点乱了
也不知道为啥…在本地markdown都是对的
应该是$里加几个空格就行了,我也经常遇到这种问题
找到问题了,将所有的星号换成\times就解决了,acwing跟typora不太一样