【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\n",++tot,res);
    }
    return 0;
}
posted @ 2021-02-14 17:58  HinanawiTenshi  阅读(86)  评论(0编辑  收藏  举报