Uva714 Copying Books 【二分】【例题8-10】

本文介绍了一种解决CopyingBooks问题的算法,该问题要求将m个序列分割成k个连续子序列,使得子序列和的最大值尽可能小。通过二分查找及遍历序列的方法,实现了对序列的有效分割。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:Copying Books

题意:将m个序列分成k个连续的子序列,将各个子序列求和,分的子序列的和的最大值尽量小。

思路:

(1)枚举子序列和的最大值,从m个序列中最大值~m个序列的和 之间的数二分枚举最大值,每次枚举的值看能划分的个数与k值比较,如果<=k 枚举值小缩小,否则增大,直到二分结束后,左值即为最大值的尽量小化。如果直接找到一次相等k的话不能不是尽量小化,所以继续进行二分!

(2)求划分个数:遍历一遍序列,连续累加数字,当加上下一位时大于当前枚举的最大值时就要划分了!

(3)打印划分:用一个标记数组,倒的遍历序列(因为要靠前的尽量小,所以先算后面的尽量达到最大值,剩下前面的数肯定少了就小了!)继续连续累加数字,当加上下一位大于最大值的话就将此位置标记1即为划分,并且将划分次数减少一次,  或者 当划分次数大于等于剩余数个数时必须划分了,因为有可能连续和还没有加到最大值,还一直加,此时剩余的个数不够满足k次划分了!

(4)输出原序列且当标记数组为1时输出"/"。

参考:紫书代码库

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 500 + 5;
int s[maxn],mark[maxn],n,k;
inline int P(LL v){//最大值最小化为v时划分的次数
    int cnt = 1;
    LL sum = 0;
    for(int i=0;i<n;i++){
        if(sum + s[i] < v) sum += s[i];//向右划分
        else{sum = s[i];cnt++;}//记录划分次数
    }
    return cnt;
}
inline int binarySearch(LL l,LL r){//二分查找最大值
    while(l < r){
        LL pos = l + (r - l)/2;
        if(P(pos) <= k) r = pos;//当划分次数小于k时说明当前最大值大了,右值缩小
        else l = pos + 1;//
    }
    return l;
}
inline void divide(int ans){//划分
    memset(mark,0,sizeof(mark));
    LL sum = 0;
    int cnt = k;
    for(int i=n-1;i>=0;i--)
        if(sum + s[i] > ans || i+1 < cnt){//当和大于最大值 或  剩余的元素个数已经等于当前剩余的划分个数时必须划分,因为要求划分k次!
            sum = s[i];//将求和归位,继续下一次的相加
            mark[i] = 1;//在当前位置划分
            cnt--;//划分次数减少
        }
        else sum += s[i];

    for(int i=0;i<n-1;i++){
        printf("%d ",s[i]);
        if(mark[i]) printf("/ ");
    }
    printf("%d\n",s[n-1]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        int maxp = -1;
        LL sum = 0;
        for(int i=0;i<n;i++) {
            scanf("%d",&s[i]);
            maxp = max(maxp,s[i]);//求最大值,用作二分查找最大值的左值
            sum += s[i];//求和,用作二分查找最大值的右值
        }
        divide(binarySearch((LL)maxp,sum));
    }
    return 0;
}



<think>好的,我现在要解决用户提到的Java模块循环依赖导致注解处理失败的问题。用户提到了几个模块,比如htypc-school、ruoyi-common-redis等,需要排除某些模块的注解处理。首先,我需要理解什么是模块循环依赖以及它如何影响注解处理。 首先,模块循环依赖指的是两个或多个模块互相依赖,形成一个闭环。比如模块A依赖模块B,模块B又依赖模块A。这种情况在构建时会导致问题,尤其是当使用注解处理器时,因为编译器需要按顺序处理模块,而循环依赖会打破这个顺序,导致注解处理器无法正确执行。 接下来,我需要考虑用户的具体项目结构。用户提到了多个ruoyi-common模块,这可能是一个基于若依框架(RuoYi)的项目,该框架是一个开源的企业级快速开发平台。常见的模块如common-core、common-redis、common-log等通常包含通用工具类和基础配置,而api-system可能涉及系统接口。如果这些模块之间存在循环依赖,特别是在编译时涉及注解处理的部分,就会引发错误。 用户的问题中的错误类型是“annotation processing error”,这通常发生在注解处理器无法正确生成代码时,可能是因为依赖的模块尚未编译,导致处理器找不到所需的类或资源。例如,如果模块A的注解处理需要模块B中的某个类,但模块B又依赖模块A,那么在编译模块A时,模块B可能还没有被编译,从而导致失败。 接下来,我需要思考如何排除模块的注解处理。在Maven或Gradle中,可以通过配置来排除特定的依赖模块参与注解处理。例如,在Maven的maven-compiler-plugin中,可以设置annotationProcessorPaths来指定哪些依赖应作为注解处理器,或者排除某些模块。 另外,用户提到需要排除的模块包括ruoyi-common-redis、ruoyi-common-log等,这些模块可能包含自定义的注解处理器,或者它们的依赖关系导致循环。例如,如果ruoyi-common-core模块引用了ruoyi-common-security的注解,而security又引用了core的某些类,这就会形成循环。 解决方案可能需要分步骤进行。首先,检查各个模块的pom.xml或build.gradle文件,确认依赖关系,找出循环链。然后,重构代码,打破循环,比如将公共部分提取到更底层的模块中。如果无法立即重构,可以临时排除某些模块的注解处理,确保编译顺序正确。 例如,在Maven中,可以在依赖声明中使用<exclusions>标签来排除特定的传递依赖。或者,在编译器插件中配置不将某些模块作为注解处理器处理。例如: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths> <!-- 排除ruoyi-common-redis等模块 --> <path> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-redis</artifactId> <version>${ruoyi.version}</version> <exclusions> <exclusion> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-core</artifactId> </exclusion> </exclusions> </path> </annotationProcessorPaths> </configuration> </plugin> ``` 另外,检查是否有模块在注解处理器中引用了其他模块的类,导致编译顺序问题。可能需要调整模块结构,将注解处理器相关的代码独立出来,或者确保依赖顺序正确。 用户还提到了数据范围切面和动态SQL改写,这可能涉及到AOP和MyBatis的拦截器,这部分如果涉及注解处理,也需要确保相关模块的依赖正确,没有循环引用。 最后,建议用户使用工具分析模块依赖,比如Maven的依赖树命令(mvn dependency:tree),找出循环的具体路径,然后针对性地排除或重构。如果时间紧迫,排除特定模块的注解处理可能是临时解决方案,但长期还是需要优化模块结构,避免循环依赖。</think>### Java模块循环依赖导致注解处理失败的解决方案 #### 1. 确认循环依赖路径 首先使用Maven依赖树分析工具定位问题模块: ```bash mvn dependency:tree -Dincludes=com.ruoyi:* ``` 检查输出中是否存在如`ruoyi-common-core → ruoyi-api-system → ruoyi-common-core`的循环链[^3]。 #### 2. 排除特定模块的注解处理 在**父POM**或**子模块的pom.xml**中配置注解处理器过滤: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths> <!-- 显式声明需要保留的处理器 --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </path> <!-- 排除冲突模块 --> <path> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-redis</artifactId> <version>${ruoyi.version}</version> <exclusions> <exclusion> <groupId>*</groupId> <!-- 阻断所有传递依赖 --> <artifactId>*</artifactId> </exclusion> </exclusions> </path> </annotationProcessorPaths> </configuration> </plugin> ``` #### 3. 模块化重构建议 对于长期解决方案,建议: 1. 将通用注解提取到独立模块`ruoyi-annotations` $$ \text{ruoyi-annotations} \rightarrow \text{ruoyi-common-core} $$ 2. 数据权限相关代码重构为独立服务模块 ```java // 原数据范围切面改造为SPI接口 public interface DataScopeProvider { String generateFilter(); } ``` #### 4. 动态配置调整 在`ruoyi-test-dev.yml`中添加注解处理隔离配置: ```yaml annotation-processing: excluded-modules: - ruoyi-common-datascope - ruoyi-common-security enabled-processors: - lombok - mapstruct ``` 通过环境变量控制处理范围[^2]。 #### 5. 验证步骤 1. 执行清理构建: ```bash mvn clean install -DskipTests ``` 2. 检查`target/generated-sources`目录是否包含预期生成的代码 3. 使用JDK工具分析依赖: ```bash jdeps --multi-release 11 --print-module-deps target/*.jar ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值