【DP+贪心】能量石

题面https://www.acwing.com/problem/content/736/

分析:

这是一道基于贪心和DP的题目,可以从分析两个相邻物品的顺序入手:

对相邻的两个物品 (i), (i+1)
记取到它们的时候(假设它们的能量在这个过程中都没有耗尽)它们的属性是: (s_{i},e_{i},l_{i};s_{i+1},e_{i+1},l_{i+1})

运用类似的排序思想的题目还有:https://www.acwing.com/problem/content/description/127/

如果按照先 (i), 然后 (i+1) 的顺序选,那么应有:

[e_{i}+e_{i+1}-s_{i}l_{i+1} > e_{i+1}+e_{i}-s_{i+1}l_{i} ]

即:(s_{i}l_{i+1} < s_{i+1}l_{i}) ,从中我们得到了贪心的取物品顺序。

然后就转化为01背包问题了,注意,这里的状态 (f_j) 表示是若时间恰为 (j) 所能得到的最大价值,如果不这样表示则无法正确处理时间导致的能量损失问题。

代码

#include<bits/stdc++.h>
using namespace std;

const int N=110, M=1e4+5;

struct node{
    int s,e,l;
}a[N];

bool cmp(node a,node b){
    return a.s*b.l<a.l*b.s;
}
int T,tot;
int n;

int f[M];

int main(){
    cin>>T;
    while(T--){
        
        memset(f,0xcf,sizeof f);
        f[0]=0;
        
        cin>>n;
        
        int t=0; //总时间
        for(int i=1;i<=n;i++){
            cin>>a[i].s>>a[i].e>>a[i].l;
            t+=a[i].s;
        }
        
        sort(a+1,a+1+n,cmp);
        
        for(int i=1;i<=n;i++){
            int s=a[i].s,e=a[i].e,l=a[i].l;
            for(int j=t;j>=s;j--){
                f[j]=max(f[j],max(f[j-s]+e-(j-s)*l,0));
            }
        }
        
        int res=0;
        for(int i=0;i<=t;i++) res=max(res,f[i]);
        
        printf("Case #%d: %d
",++tot,res);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Tenshi/p/14402320.html