活动安排问题(贪心、Java)

活动安排问题(贪心、Java)

又是好久没更,最近一直在忙杂七杂八的,更一个算法作业吧。

问题

X轴上有N条线段,每条线段有1个起点S和终点E。最多能够选出多少条互不重叠的线段。(注:起点或终点重叠,不算重叠)。

或者

设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi。如果选择了活动i,则它在半开时间区间[si ,fi )内占用资源。若区间[si ,fi )与区间[sj,fj )不相交,则称活动i与活动j是相容的。当 si ≥ fj 或 sj ≥ fi 时,活动i与活动j相容。
活动安排问题就是在所给的活动集合中选出最大的相容活动子集合。
图片来自https://www.jianshu.com/p/5a97bcc407fa?tdsourcetag=s_pctim_aiomsg

分析

开始最早的方案基本不用考虑,这里不解释。

我最初的方法是先找时间间隔最短的,这样就可以留出足够多的时间去举办别的活动。
但是我忽略了一点,这样分割出来的很有可能是不间隔的两段时间段。按照这个规则选取活动的话,取一两次之后时间可能就被分割成不同大小的不连续小段,这样肯定不能再用了。

在这里插入图片描述
那我们就让剩余的时间段连续起来,还要最大,那么我们就选择结束时间最早的,这样留出来的是整块的时间还挺大。
在这里插入图片描述

代码

/**
 * @ClassName ActivityArrangement
 * @Description 活动安排问题 贪心算法 不考虑整体最优而专注局部最优解
 *
 *设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,
 * 而在同一时间内只有一个活动能使用这一资源。
 * 每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi。
 * 如果选择了活动i,则它在半开时间区间[si ,fi )内占用资源。若区间[si ,fi )与区间[sj,fj )不相交,
 * 则称活动i与活动j是相容的。当 si ≥ fj 或 sj ≥ fi 时,活动i与活动j相容。
 * 活动安排问题就是在所给的活动集合中选出最大的相容活动子集合。
 *
 *
 * @author 滑技工厂 https://blog.csdn.net/qq_41718454
 * @date 2020/6/5
 * @version 1.0
 */
public class ActivityArrangement {

    /*
     * @Title chooseActivity
     * @Description 选择活动方法
     * @author 滑技工厂
     * @Date 2020/6/5
     * @param [activities]
     * @return boolean[] 返回活动选择数组
     * @throws
     */
    public static boolean[] chooseActivity(Activity[] activities) {
        int n = activities.length;
        //用来表示原活动序列(未排序)是否被选中
        boolean[] flags = new boolean[n];

        //把序列按照结束时间进行升序排序
        Arrays.sort(activities);

        //结束时间指针
        int flag = 0;

        for (int i = 0; i < n; i++) {
            //排序之后,如果一个活动的开始时间在指针之后或相等,那么便可以举办这个活动
            if (activities[i].starttime>=flag){
                //举办活动 更新结束时间指针
                flag = activities[i].finaltime;
                flags[activities[i].index] = true;
            }
        }
        return flags;
    }


    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt();
        Activity activities[] = new Activity[n];

        for (int i = 0; i < n; i++) {
            activities[i] = new Activity();
            activities[i].index = i;
            activities[i].starttime = sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            activities[i].finaltime = sc.nextInt();
        }

        boolean[] flags = chooseActivity(activities);

        for (boolean flag : flags) {
            System.out.print(flag+" ");
        }

    }

}
/**
 * @ClassName Activity
 * @Description 活动类
 * @author 滑技工厂 https://blog.csdn.net/qq_41718454
 * @date 2020/6/5
 * @version 1.0
 */
class Activity implements Comparable<Activity> {
    int index;
    int starttime;
    int finaltime;
    /*
     * @Title compareTo
     * @Description 排序方法
     * @author 滑技工厂
     * @Date 2020/6/5
     * @param [activity]
     * @return int 1表示this对象要排前面 -1表示不排前面
     * @throws
     */
    @Override
    public int compareTo(Activity activity) {
        if (activity.finaltime > this.finaltime)
            return -1;
        else if (activity.finaltime == this.finaltime)
            return 0;
        else
            return 1;
    }

好久没更新十分抱歉,感到有帮助的话请给个大大的点👍,给我一些些的动力🙏🙏

在这里插入图片描述

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
活动安排问题是一道经典的贪心算法问题,它的目标是从一组活动中选择出最多的相互兼容的活动。以下是活动安排问题的具体描述: 有n个活动要占用同一块资源(如一个房间),每个活动ai有一个开始时间si和结束时间fi(si<fi),只有在时间区间[si,fi)内才能进行这个活动。若区间[si,fi]与区间[sj,fj]不相交,则称活动ai与aj是相互兼容的。你的目标是选出尽量多的相互兼容的活动。 下面是该问题的贪心算法实现过程(假设所有活动按照结束时间从小到大排序): 1. 选取结束时间最早的活动; 2. 从剩余的活动中选取与已选中的最后一个活动相兼容且结束时间最早的活动; 3. 重复步骤2,直到没有剩余的活动。 以下是Java代码实现: ``` import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ActivitySelection { public static List<Activity> activitySelection(List<Activity> activities) { List<Activity> selectedActivities = new ArrayList<>(); if (activities.isEmpty()) { return selectedActivities; } // 将所有活动按照结束时间从小到大排序 Collections.sort(activities, new Comparator<Activity>() { @Override public int compare(Activity o1, Activity o2) { return o1.getEnd() - o2.getEnd(); } }); // 选取第一个结束时间最早的活动 selectedActivities.add(activities.get(0)); int lastSelectedEnd = activities.get(0).getEnd(); // 从剩余的活动中选取与已选中的最后一个活动相兼容且结束时间最早的活动 for (int i = 1; i < activities.size(); i++) { Activity activity = activities.get(i); if (activity.getStart() >= lastSelectedEnd) { selectedActivities.add(activity); lastSelectedEnd = activity.getEnd(); } } return selectedActivities; } public static void main(String[] args) { List<Activity> activities = new ArrayList<>(); activities.add(new Activity(1, 4)); activities.add(new Activity(3, 5)); activities.add(new Activity(0, 6)); activities.add(new Activity(5, 7)); activities.add(new Activity(3, 8)); activities.add(new Activity(5, 9)); activities.add(new Activity(6, 10)); activities.add(new Activity(8, 11)); activities.add(new Activity(8, 12)); activities.add(new Activity(2, 13)); activities.add(new Activity(12, 14)); List<Activity> selectedActivities = activitySelection(activities); System.out.println("选中的活动:"); for (Activity activity : selectedActivities) { System.out.println(activity); } } } class Activity { private int start; private int end; public Activity(int start, int end) { this.start = start; this.end = end; } public int getStart() { return start; } public int getEnd() { return end; } @Override public String toString() { return "[" + start + ", " + end + "]"; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值