• 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;
        }
    }
    
  • 相关阅读:
    Java程序员极力推荐的springboot全家桶干货系列——收藏必会系列
    mysql 远程连接数据库的二种方法
    mysql取以当前时间为中心的任意时间段的时间戳
    使用sql语句,查询 mysql 的安装地址
    MyEclipse中点击Deploy MyEclipse J2EE Project to Server无响应解决方法
    使用DOS访问数据库详解
    mysql查询字段为null 返回0
    MySQL触发器Trigger实例篇
    JAVA汉字转拼音(取首字母大写)
    阿里云上传文件
  • 原文地址:https://www.cnblogs.com/doubest/p/16114407.html
Copyright © 2020-2023  润新知