成魔之路−> 算法提高课题解
结论: 按 sili 从小到大排序
证明:
先吃第 i 块能量石,再吃第 i+1 块能量石,所得能量:e′i+e′i+1−si⋅li+1
先吃第 i+1 块能量石,再吃第 i 块能量石,所得能量:e′i+1+e′i−si+1⋅li
若让前者大于后者,则 sili<si+1li+1
可参考: 耍杂技的牛
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N = 110, M = 10010;
int n;
struct Stone
{
int s,e,l;
bool operator< (const Stone &W) const
{
return s*W.l<l*W.s;
}
}stone[N];
int f[M]; //从前 i 个物品中选,体积恰好是 j 的最大价值
int main()
{
int T;
cin>>T;
for(int Case=1;Case<=T;Case++)
{
cin>>n;
int m=0;
for(int i=0;i<n;i++)
{
int s,e,l;
cin>>s>>e>>l;
stone[i]={s,e,l};
m+=s;
}
sort(stone,stone+n); //排序
memset(f,0,sizeof f); //多组数据初始化
// 01 背包
for(int i=0;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); // e - (j - s) * l 有可能是负数
}
int res=0;
for(int i=0;i<=m;i++) res=max(res,f[i]); //找到最优解
printf("Case #%d: %d\n",Case,res);
}
return 0;
}