UVA 12124 Assemble(贪心 二分)

本文介绍了一个基于二分搜索算法的优化方案,用于在有限预算内组装个人电脑,并确保所选配件中品质最差的部件其品质因子尽可能高。通过删除低于设定阈值的配件并选择每种类别中最经济的选项来实现这一目标。
题目大意:

你有b块钱,想要组装一台电脑。给出n个配件各自的种类、品质因子和价格,要求每种类型的配件各买一个,总价格不超过b,且“品质最差配件”的品质因子应尽量大。
【输入格式】
输入的第一行为测试数据组数T(T≤100)。每组数据的第一行为两个正整数n(1≤
n≤1 000)和b(1≤b≤109),即配件的数目和预算;以下n行每行描述一个配件,依次为种类、名称、价格和品质因子。其中,价格为不超过106的非负整数;品质因子是不超过109的非负整数(越大越好);种类和名称则由不超过20个字母、数字和下划线组成。输入保证总是有解。
【输出格式】
对于每组数据,输出配件最小品质因子的最大值。

分析:

在《入门经典》一书中,我们曾提到过,解决“最小值最大”的常用方法是二分答案。假设答案为x,如何判断这个x是最小还是最大呢?删除品质因子小于x的所有配件,如果可以组装出一台不超过b元的电脑,那么标准答案ans≥x,否则ans<x。
如何判断是否可以组装出满足预算约束的电脑呢?很简单,每一类配件选择最便宜的一个即可。如果这样选都还超预算的话,就不可能有解了。

import java.util.*;

public class Main {
    static int cnt ,n, b;
    static HashMap<String,Integer> id = new HashMap<String,Integer>();
    static ArrayList<ArrayList<Component>> comps = null;
    static Integer ID(String s) {
        int res=0;
        if(id.containsKey(s)) {
            res=id.get(s);
        }else {
            id.put(s, cnt);
            res = cnt;
            cnt++;
        }
        return res;
    }
    static void init() {
        cnt = 0;
        id.clear(); //初始化id
        comps = new ArrayList<ArrayList<Component>>();
        for(int i=0;i <= n;i++) {
            ArrayList<Component> tmp =new ArrayList<Component>();
            comps.add(tmp);
        }
    }
    static boolean judge(int q) {
        int sum = 0;
        for(int i = 0; i < cnt; i++) {
            int cheapest = b + 1;
            for(int j = 0; j < comps.get(i).size(); j++) {
                if(comps.get(i).get(j).quality >= q)
                    cheapest = Math.min(cheapest, comps.get(i).get(j).price);
            }
            if(cheapest == b + 1) {
                return false;
            }
            sum += cheapest;
            if(sum > b) {
                return false;
            }
        }
        return true;
    }
    public static void main(String []args) {
        Scanner cin = new Scanner(System.in);
        int T;
        T = cin.nextInt();
        while(T-- > 0) {
            n = cin.nextInt();
            b = cin.nextInt();

            init();
            int maxq = Integer.MIN_VALUE , minq = Integer.MAX_VALUE;
            String type, name;
            int p , q;
            for(int i = 0; i < n; i++) {
                type = cin.next();
                name = cin.next();
                p = cin.nextInt();
                q = cin.nextInt();
                maxq = Math.max(maxq,q);
                minq = Math.min(minq,q);
                int num = ID(type);
                comps.get(num).add(new Component(p,q));
            }
            int left = minq , right = maxq;
            while(left < right) {
                int mid = left + (right - left + 1) / 2;
                if(judge(mid)) {
                    left = mid;
                }else {
                    right = mid - 1;
                }
            }
            System.out.printf("%d\n", left);
        }
    }
}

class Component {
    int price;
    int quality;
    Component(int p,int q) {
        this.price = p;
        this.quality = q;
    }
}
<think>我们正在讨论的是如何在Gradle中配置自动分类打包(assemble)。根据用户之前的上下文,用户已经了解了`minifyEnabled`的作用和配置,现在希望进一步了解如何通过Gradle命令来自动化打包,特别是如何根据不同的分类(比如不同的productFlavor和buildType)进行打包。 从引用[1]中我们可以知道,Gradle提供了`assemble`命令来编译所有productFlavor和buildType的APK,同时也可以指定特定的productFlavor和buildType来编译特定的APK。例如: - `gradle assemble`:编译所有变体 - `gradle assembleFlavorRelease`:编译特定flavor的release版本 用户希望的是“自动分类打包”,也就是能够按照一定的分类(比如不同的渠道、不同的构建类型)自动执行打包任务。我们可以通过配置Gradle的构建变体(build variants)来实现,构建变体由productFlavor和buildType组合而成。 ### 配置步骤 #### 1. 定义productFlavors(渠道) 在`build.gradle`文件中,我们可以定义多个productFlavor,每个代表一个渠道或一个分类。例如: ```groovy android { flavorDimensions "version" productFlavors { free { dimension "version" // 这里可以配置free版本特有的设置 } paid { dimension "version" // 这里可以配置paid版本特有的设置 } } } ``` #### 2. 定义buildTypes(构建类型) 通常,Android项目默认有debug和release两种构建类型。我们也可以自定义其他类型,例如: ```groovy android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { minifyEnabled false } staging { // 可以复制release的配置,然后修改部分 initWith release // 例如,修改applicationId后缀 applicationIdSuffix ".staging" } } } ``` #### 3. 组合构建变体 配置了productFlavors和buildTypes后,Gradle会自动生成对应的构建变体(variants)。例如,上面的配置会生成以下变体: - freeDebug - freeRelease - freeStaging - paidDebug - paidRelease - paidStaging #### 4. 执行分类打包 我们可以通过以下命令来打包特定的变体: - 打包所有变体:`gradle assemble`(或`./gradlew assemble`) - 打包所有free变体:`gradle assembleFree`(这会生成freeDebug, freeRelease, freeStaging) - 打包所有release变体:`gradle assembleRelease`(这会生成freeRelease, paidRelease) - 打包特定的变体:`gradle assembleFreeRelease` #### 5. 自动化打包脚本 我们可以编写一个脚本(如shell脚本或bat脚本)来执行一系列Gradle命令,实现自动分类打包。例如,一个简单的shell脚本(macOS/Linux): ```bash #!/bin/bash # 打包所有free版本 ./gradlew assembleFree # 打包所有paid的release版本 ./gradlew assemblePaidRelease ``` 对于Windows,可以编写一个bat脚本: ```bat @echo off gradlew assembleFree gradlew assemblePaidRelease ``` #### 6. 进阶:使用Gradle任务依赖 我们也可以自定义Gradle任务,将多个打包任务组合起来。例如,在`build.gradle`中定义一个任务,让它依赖于多个assemble任务: ```groovy task assembleAllFree(type: GradleBuild) { tasks = ['assembleFreeDebug', 'assembleFreeRelease', 'assembleFreeStaging'] } task assembleAllPaid(type: GradleBuild) { tasks = ['assemblePaidDebug', 'assemblePaidRelease', 'assemblePaidStaging'] } task assembleAllRelease(type: GradleBuild) { tasks = ['assembleFreeRelease', 'assemblePaidRelease'] } ``` 然后就可以通过`gradle assembleAllFree`等命令来执行分类打包。 ### 注意事项 - 在命令行中执行Gradle命令时,使用`gradlew`(Gradle Wrapper)而不是全局的`gradle`命令,这样可以保证使用项目指定的Gradle版本。 - 如果项目是多模块的,可以在命令中指定模块,例如:`gradlew :app:assembleFreeRelease`。 ### 引用说明 根据引用[1],我们了解到Gradle的assemble命令可以指定productFlavor和buildType,并且支持缩写。引用[2]和[3]则提供了关于自动化打包的配置和环境设置的背景。引用[4]提到了敏感信息的处理,虽然与当前问题不直接相关,但在实际打包中,如果涉及签名和加固,可以参考其方法。 ### 总结 通过配置productFlavors和buildTypes,我们可以定义多个构建变体,然后使用Gradle的assemble命令按分类打包。同时,我们可以通过脚本或自定义Gradle任务来进一步自动化这个过程。 §§相关问题§§ 1. 如何在Gradle中配置多渠道打包(如友盟统计)? 2. 如何自定义Gradle任务以实现更复杂的打包流程? 3. 在自动化打包中,如何自动增加版本号并生成对应APK文件名? 4. 如何通过Gradle命令只打包特定模块?</think>在 Gradle 中配置自动分类打包(assemble)主要通过 **productFlavors** 和 **buildTypes** 的组合实现,以下是详细配置步骤和示例: ### 一、核心配置方法(build.gradle) ```groovy android { // 1. 定义构建类型 buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { applicationIdSuffix ".debug" // 添加调试后缀 } staging { // 自定义构建类型 initWith release // 继承release配置 applicationIdSuffix ".staging" } } // 2. 定义产品风味(分类维度) flavorDimensions "channel", "version" productFlavors { // 渠道维度 free { dimension "channel" applicationIdSuffix ".free" } paid { dimension "channel" applicationIdSuffix ".paid" } // 版本维度 basic { dimension "version" versionNameSuffix "-basic" } pro { dimension "version" versionNameSuffix "-pro" } } } ``` ### 二、打包命令分类执行 配置后会自动生成组合任务,按分类执行打包: ```bash # 1. 打包所有变体 ./gradlew assemble # 2. 按构建类型打包 ./gradlew assembleRelease # 所有release版本 ./gradlew assembleDebug # 所有debug版本 ./gradlew assembleStaging # 所有staging版本 # 3. 按渠道打包 ./gradlew assembleFree # 所有free渠道变体 ./gradlew assemblePaid # 所有paid渠道变体 # 4. 按版本打包 ./gradlew assembleBasic # 所有基础版 ./gradlew assemblePro # 所有专业版 # 5. 精确组合打包 ./gradlew assembleFreeProRelease # free渠道+pro版+release类型 ./gradlew assemblePaidBasicDebug # paid渠道+basic版+debug类型 ``` ### 三、自动化打包增强技巧 1. **自动输出路径配置** 在`build.gradle`中添加APK重定向: ```groovy android.applicationVariants.all { variant -> variant.outputs.all { output -> def formattedDate = new Date().format('yyyyMMdd') outputFileName = "${variant.flavorName}_${variant.buildType.name}_v${variant.versionName}_${formattedDate}.apk" } } ``` 2. **敏感信息安全处理**(引用[4]) 创建`secrets.properties`文件: ```properties KEY_PATH=/path/to/keystore KEY_PASSWORD=your_password ``` 在`build.gradle`中读取: ```groovy def secrets = new Properties() file("secrets.properties").withInputStream { secrets.load(it) } signingConfigs { release { storeFile file(secrets.getProperty("KEY_PATH")) storePassword secrets.getProperty("KEY_PASSWORD") } } ``` ### 四、典型目录结构 ``` app/ ├── build/ │ └── outputs/ │ └── apk/ │ ├── free/ # 免费渠道 │ │ ├── debug/ │ │ └── release/ │ └── paid/ # 付费渠道 │ ├── debug/ │ └── release/ └── src/ ├── free/ # 免费渠道专属代码 ├── paid/ # 付费渠道专属代码 └── main/ # 公共代码 ``` ### 五、执行效果示例 ```bash $ ./gradlew assembleFreeRelease > 生成APK: app-free-release-v1.0_20230815.apk $ ./gradlew assemblePaidBasicDebug > 生成APK: paid-basic-debug-v1.0_20230815.apk ``` > **最佳实践**:结合持续集成(CI)工具(如Jenkins),可通过`./gradlew assembleFreeRelease assemblePaidRelease`实现每日自动构建[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值