贪心算法-活动安排问题

本文介绍了如何使用贪心算法解决活动安排问题,旨在安排尽可能多的活动在同一资源上进行。活动按照结束时间升序排列,通过比较活动结束时间和下一个活动开始时间,确保不相交,从而选择相容的活动。文章提供了算法分析和一个11个活动的示例,通过排序优化了算法效率,达到O(n)的时间复杂度。

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

贪心算法-活动安排问题

活动安排问题是可以用贪心算法有效求解的很好的例子。
问题:有n个活动的集合A={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。
求解:安排尽量多项活动在该场地进行,即求A的最大相容子集。
设待安排的11个活动的开始时间和结束时间按结束时间的升序排列如下:

i1234567891011
s[i]130535688212
f[i]4567891011121314

将此表数据作为实现该算法的测试数据。
【算法分析】
分析:每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
例:给出待安排的11个活动的开始时间和结束时间,要求安排尽量多项活动使用会场。
首先,任意输入这11个活动。
然后对活动以其完成时间的非减序排列。(意义:使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。)
将第一次活动结束时间f[1]与后面活动开始时间s[2]相比较,若s[2]<f[1]则继续比较,直到s[4]>f[1],选中此活动。再用活动4的结束时间f[4]与其后活动的开始时间比较……同理类推,直到比较完成为止,最后选出合条件的活动1,活动4,活动8和活动11,它们将依次被安排使用该场地。
具体代码:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/*
测试数据我把它倒过来了,方便测试代码的排序和活动id的正确
11
12 14
2 13
8 12
8 11
6 10
5 9
3 8
5 7
0 6
3 5
1 4
 */
public class 贪心算法 {
	/*
	 方法一。运用数组来排序和实现,算法时间复杂度高。
	 
	static int n;
	static int[] s;
	static int[] f;
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		n=input.nextInt();
		s=new int[n];
		f=new int[n];
		for(int i=0;i<n;i++) {
			s[i]=input.nextInt();
			f[i]=input.nextInt();
		}
		for(int i=0;i<n;i++) {
			for(int j=i;j<n;j++) {
				if(f[j]<f[i]) {
					{int temp=f[j];f[j]=f[i];f[i]=temp;}
					{int temp=s[j];s[j]=s[i];s[i]=temp;}
				}
			}
		}
		int[] x=new int[n];
		x[0]=1;
		int j=f[0];
		for(int i=0;i<n;i++) {
			if(s[i]>j) {
				j=f[i];
				x[i]=1;
			}
		}
		for(int i=0;i<n;i++) {
			if(x[i]==1) {
				System.out.print(i+1+" ");
			}
		}
	}*/
	
	
	/*我创建了一个类来体现活动的标号(id)和开始时间(s),结束时间(f)
	 *运用Comparable接口重写了 compareTo()方法
	 *然后吧Node储存在集合里,然后利用Collections进行sort排序,把Node进行整体排序
	 */
	static class Node implements Comparable<Node>{
		int id;
		int s;
		int f;
		@Override
		public int compareTo(Node o) {
			Integer a=this.f;
			Integer b=o.f;
			return a.compareTo(b);
		}
		@Override
		public String toString() {
			return "Node [id=" + id + ", s=" + s + ", f=" + f + "]";
		}
		
	}
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n=input.nextInt();
		List<Node> list=new ArrayList<Node>();
		for(int i=0;i<n;i++) {
			Node node=new Node();
			node.id=i+1;
			node.s=input.nextInt();
			node.f=input.nextInt();
			list.add(node);
		}
		Collections.sort(list);
		Node node1=list.get(0);
		int j=node1.f;
		System.out.print(node1.id);
		for(Node nd:list) {
			if(nd.s>j) {
				j=nd.f;
				System.out.print(" "+nd.id);
			}
		}
	}

}

后面的方法应该比较优化了,用快排的效率肯定比冒泡快很多=。=,把时间复杂度降到O(n)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值