活动安排问题

1.问题描述
输入: 活动的数量,以及每个活动的开始时间和结束时间
输出:最大相容活动集合的序列,以及开始时间和结束时间
2.实验目的
通过活动安排问题理解贪心选择思想,掌握活动安排问题的算法并通过编程练习加深理解。
3.实验原理
设有n个活动的集合E={1,2,3,…,n},其中每个活动都要求使用同一资源,每个活动都有一个使用该资源的开始时间Si和结束时间Fi,且Si<Fi。当Si≧Fj或者Sj≧Fi时活动i与活动j相容。
4.实验设计
private static void greedySelector(int n, int[] s, int[] f, boolean[] A) {
A[0]=true;//第一个活动被选中
int j=0;
for(int i=1;i<=n;i++){
if(s[i]>f[j]){//下一个活动的开始时间大于等于上一个活动的结束时间就可以选
A[i]=true;
j=i;
}else{//否则就不选
A[i]=false;
}
}
}
5.实验结果与分析
贪心算法并不是总能求得问题的整体最优解,但是对于活动安排问题,贪心算法却总能求得问题的整体最优解。关键在于对活动按结束时间进行了升序排列,所以每次选择的都是结束时间最早的,以达到尽可能多的安排活动,这体现了贪心选择性质。
6.结论
活动安排问题是可以用贪心算法求解的很好的例子,它能够很好的反映贪心算法的思想,要运用贪心选择算法需要问题具有最优子结构性质和贪心选择性质。

public class Greedy {
    private static int lastEnd;

    public static void main(String[] args) {
        List<Action> list = new ArrayList<>();
        @SuppressWarnings("resource")
		Scanner sc = new Scanner(System.in);
        System.out.println("请输入活动的数量:");
        int x = sc.nextInt();
        
        for(int i=1;i<=x;i++){
        	System.out.println("请输入第"+i+"活动的开始时间:");
        	int start = sc.nextInt();
        	System.out.println("请输入第"+i+"个活动的结束时间:");
        	int end = sc.nextInt();
        	
        	Action action =new Action();
        	action.setStart(start);
        	action.setEnd(end);
        	
        	list.add(action);
        }

//        list.add(new Action(2, 5));
//        list.add(new Action(3, 7));
//        list.add(new Action(1, 6));
//        list.add(new Action(11, 20));
//        list.add(new Action(8, 9));
//        list.add(new Action(0, 3));

        List<Action> actions = new ArrayList<>();

        int minNum = 0;
        int min = list.get(0).getStart();
        //拿到所有活动中,开始时间最早的那一个
        for (int i = 1; i < list.size(); i++) {
            int as = list.get(i).getStart();
            if (as < min)
                minNum = i;
        }

        //第一个活动
        Action firstAction = list.get(minNum);
        firstAction.setCheck(true);
        lastEnd = firstAction.getEnd();
        //添加到集合
        actions.add(firstAction);
        list.remove(firstAction);

        Action nextAction;
        while ((nextAction = nextAction(list)) !=null) {

            nextAction.setCheck(true);
            lastEnd = nextAction.getEnd();
            actions.add(nextAction);
            list.remove(nextAction);
        }

        for (Action action : actions) {
            System.out.println("action =" + action.toString());
        }

        System.out.println("-------------------------------------------------");
        if (list.size() > 0) {
            for (Action a : list) {
                System.out.println("action =" + a.toString());
            }
        }
    }

    private static Action nextAction(List<Action> list) {

        int size = list.size();
        int minInt = -1;
        int minNumber = -1;
        int[] ss = new int[size];

        for (int h = 0; h < size; h++) {
            //赋初值,唔 。。。这里应该可以改一下
            ss[h] = -1;
        }

        //计算集合中活动的开始时间和存储的上一次活动的结束时间的差值
        for (int i = 0; i < size; i++) {
            Action action = list.get(i);
            int start = action.getStart();
            if (start >= lastEnd) {
                ss[i] = start - lastEnd;
            }
        }

        //差值最小的就是下一个活动
        for (int m = 0; m < size; m++) {
            int s = ss[m];
            if (s != -1) {
                if (minInt == -1) {
                    minInt = s;
                    minNumber = m;
                } else {
                    if (s < minInt) {
                        minNumber = m;
                    }
                }
            }
        }

        if (minNumber != -1) {
            return list.get(minNumber);
        }

        return null;
    }
}
public class Action {
    private int start;
    private int end;
    private boolean isCheck = false;
    public Action() {
        super();

    }

    public Action(int start, int end) {
        super();
        this.start = start;
        this.end = end;
    }
    public int getStart() {
        return start;
    }
    public void setStart(int start) {
        this.start = start;
    }
    public int getEnd() {
        return end;
    }
    public void setEnd(int end) {
        this.end = end;
    }
    public boolean isCheck() {
        return isCheck;
    }
    public void setCheck(boolean check) {
        isCheck = check;
    }
    @Override
    public String toString() {
        return "Action{" +
                "start=" + start +
                ", end=" + end +
                ", isCheck=" + isCheck + '}';
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值