Loading

AcWing 734. 能量石

题目链接

https://www.acwing.com/problem/content/description/736/

题解

一句话概括:考虑顺序的01背包问题
详细题解:
stone: 花费时间si, 初始能量ei, 每秒损失的能量li
假设最优解的选取序列为x1,x2,...,xk,xk+1,..xn,其中xk+1-xn选取时的能量已经为0了

我们需要保证交换x1-xk中任意两个相邻能量石之后,所能选取的总能量一定会变小
假设i=l, j=l+1 (1<=i<j<=k),选取到i时,已经消耗了t时间
为了满足条件,则有以下推论:

ei-t*li+ej-(t+si)*lj >= ej-t*lj+ei-(t+sj)*li
ei-t*li+ej-t*lj-si*lj >= ej-t*lj+ei-t*li-sj*li
si*lj <= sj*li

将原能量石顺序,按照si*lj <= sj*li进行排列
然后我们需要构建一个选取集合,必定包含最优解的序列

我们可以将最优解序列理解为,在排好序的能量石序列中,按顺序选取k个物品,不选取一些物品(xk+1-xn能量为0可以理解为不选)
最大价值是多少,是典型的01背包问题,选取k个物品,可以通过枚举时间来确定,选k个物品所耗费的时间必定在0-sum(si)之间

f[i][j]:从前i个选,花费时间恰好为j的所有方案中,能量石最大的的一种

设sx1+sx2+sx3+...+sxk=kt,即最优解选取有效能量石所花费的时间
f[n][kt]的方案集合中必定包含最优解

AC代码

import java.util.*;

public class Main {
    static int N = 110, M = 10010, inf = -0x3f3f3f3f;
    static int[][] f = new int[N][M];
    static Stone[] stones = new Stone[N];
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        for (int tt = 1; tt <= T; tt ++) {
            Arrays.fill(f[0], inf);
            f[0][0] = 0;
            int n = sc.nextInt(), m = 0;
            for (int i = 1; i <= n; i ++) {
                stones[i] = new Stone(sc.nextInt(), sc.nextInt(), sc.nextInt());
                m += stones[i].s;
            }
            Arrays.sort(stones, 1, n + 1, (o1,o2)-> o1.s*o2.l - o2.s*o1.l);
            for (int i = 1; i <= n; i ++)
                for (int j = 0; j <= m; j ++) {
                    f[i][j] = f[i - 1][j];
                    if (j >= stones[i].s) 
                        f[i][j] = Math.max(f[i][j], 
                        f[i - 1][j - stones[i].s] + Math.max(0, stones[i].e - (j - stones[i].s)*stones[i].l));
                }
            int res = inf;
            for (int i = 0; i <= m; i ++) res = Math.max(res, f[n][i]);
            System.out.printf("Case #%d: %d\n", tt, res);
        }
    }
}

class Stone {
    int s, e, l;
    
    Stone(int s, int e, int l) {
        this.s = s;
        this.e = e;
        this.l = l;
    }
}
posted @ 2022-04-07 21:39  Doubest  阅读(30)  评论(0编辑  收藏  举报