程序员与项目经理

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

/**
 * author:左程云
 */
public class SDEandPM {

    public static class Program {
        public int index;
        public int pm;
        public int start;
        public int rank;
        public int cost;

        public Program(int index, int pmNum, int begin, int rank, int cost) {
            this.index = index;
            this.pm = pmNum;
            this.start = begin;
            this.rank = rank;
            this.cost = cost;
        }
    }

    public static class PmLoveRule implements Comparator<Program> {

        @Override
        public int compare(Program o1, Program o2) {
            if (o1.rank != o2.rank) {
                return o1.rank - o2.rank;
            } else if (o1.cost != o2.cost) {
                return o1.cost - o2.cost;
            } else {
                return o1.start - o2.start;
            }
        }

    }

    // 大黑盒
    // 每一个pm,有自己的堆(PmLoveRule)
    // 每一个pm的堆里有堆顶,所有的堆顶会再组成一个,程序员堆(程序员喜好)
    // void add(...)  项目  pop()
    public static class BigQueues {
        //  PriorityQueue<Program> pmQ = pmQueues.get(i);
        private List<PriorityQueue<Program>> pmQueues;
        // 程序员堆(一个,程序员共享池)
        private Program[] sdeHeap;
        // indexes[i] -> i号pm的堆顶项目,在sde堆中处在啥位置
        private int[] indexes;
        private int heapsize; // 程序员堆的大小

        public BigQueues(int pmNum) {
            heapsize = 0;
            sdeHeap = new Program[pmNum];
            indexes = new int[pmNum + 1];
            for (int i = 0; i <= pmNum; i++) {
                indexes[i] = -1;
            }
            pmQueues = new ArrayList<>();
            // i  pmQueues.get(i)
            for (int i = 0; i <= pmNum; i++) {
                pmQueues.add(new PriorityQueue<Program>(new PmLoveRule()));
            }
        }

        // 当前是否有项目可以弹出被程序员做
        public boolean isEmpty() {
            return heapsize == 0;
        }

        /**
         * 加入对应项目经理的项目池,同时更新程序员池子
         *
         * @param program
         */
        public void add(Program program) {
            PriorityQueue<Program> pmHeap = pmQueues.get(program.pm);
            pmHeap.add(program);
            // 有可能当前的项目,成了此时pm最喜欢的项目,换堆顶,调整sde堆中的项目
            Program head = pmHeap.peek(); // 现在的堆顶
            // 之前pm在sde堆中的自己的堆顶,sde?
            int heapindex = indexes[head.pm];
            if (heapindex == -1) { // 之前没堆顶,
                sdeHeap[heapsize] = head;
                indexes[head.pm] = heapsize;
                heapInsert(heapsize++);
            } else { // 加此时的program之前,我有老堆顶
                sdeHeap[heapindex] = head;
                heapInsert(heapindex);
                heapify(heapindex);
            }
        }

        // 程序员挑项目,返回挑选的项目
        public Program pop() {
            Program head = sdeHeap[0];
            PriorityQueue<Program> queue = pmQueues.get(head.pm);
            queue.poll();
            if (queue.isEmpty()) { // 此时的pm手上没有项目了
                swap(0, heapsize - 1);
                sdeHeap[--heapsize] = null;
                indexes[head.pm] = -1;
            } else {
                sdeHeap[0] = queue.peek();
            }
            heapify(0);
            return head;
        }

        private void heapInsert(int index) {
            while (index != 0) {
                int parent = (index - 1) / 2;
                if (sdeLoveRule(sdeHeap[parent], sdeHeap[index]) > 0) {
                    swap(parent, index);
                    index = parent;
                } else {
                    break;
                }
            }
        }

        private void heapify(int index) {
            int left = index * 2 + 1;
            int right = index * 2 + 2;
            int best = index;
            while (left < heapsize) {
                if (sdeLoveRule(sdeHeap[left], sdeHeap[index]) < 0) {
                    best = left;
                }
                if (right < heapsize && sdeLoveRule(sdeHeap[right], sdeHeap[best]) < 0) {
                    best = right;
                }
                if (best == index) {
                    break;
                }
                swap(best, index);
                index = best;
                left = index * 2 + 1;
                right = index * 2 + 2;
            }
        }

        private void swap(int index1, int index2) {
            Program p1 = sdeHeap[index1];
            Program p2 = sdeHeap[index2];
            sdeHeap[index1] = p2;
            sdeHeap[index2] = p1;
            indexes[p1.pm] = index2;
            indexes[p2.pm] = index1;
        }

        private int sdeLoveRule(Program p1, Program p2) {
            if (p1.cost != p2.cost) {
                return p1.cost - p2.cost;
            } else {
                return p1.pm - p2.pm;
            }
        }

    }

    public static class StartRule implements Comparator<Program> {

        @Override
        public int compare(Program o1, Program o2) {
            return o1.start - o2.start;
        }

    }

    public static int[] workFinish(int pms, int sdes, int[][] programs) {
        /**
         * 将所有项目放入队列
         */
        PriorityQueue<Program> startQueue = new PriorityQueue<Program>(new StartRule());
        for (int i = 0; i < programs.length; i++) {
            Program program = new Program(
                    i, programs[i][0], programs[i][1], programs[i][2], programs[i][3]);
            startQueue.add(program);
        }

        /**
         * 程序员在1的时间点都可以工作
         */
        PriorityQueue<Integer> wakeQueue = new PriorityQueue<Integer>();
        for (int i = 0; i < sdes; i++) {
            wakeQueue.add(1);
        }

        BigQueues bigQueues = new BigQueues(pms);
        int finish = 0; /
        int[] ans = new int[programs.length];
        while (finish != ans.length) {
            /**
             * 最早可以工作的程序员的时间点,推动时间线
             */
            int sdeWakeTime = wakeQueue.poll();

            /**
             * 如果项目池里有项目可以启动,则添加到大队列
             */
            while (!startQueue.isEmpty()) {
                if (startQueue.peek().start > sdeWakeTime) {
                    break;
                }
                bigQueues.add(startQueue.poll());
            }
            //
            if (bigQueues.isEmpty()) { // 当前时间点并无项目可做
                wakeQueue.add(startQueue.peek().start);
            } else { // 当前时间点有项目可做
                Program program = bigQueues.pop();
                ans[program.index] = sdeWakeTime + program.cost;
                wakeQueue.add(ans[program.index]);
                finish++;
            }
        }
        return ans;
    }

    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    public static void main(String[] args) {
        int pms = 2;
        int sde = 2;
        int[][] programs = {{1, 1, 1, 2}, {1, 2, 1, 1}, {1, 3, 2, 2}, {2, 1, 1, 2}, {2, 3, 5, 5}};
        int[] ans = workFinish(pms, sde, programs);
        printArray(ans);
    }

}
上一篇:每日学习--python debug调试(pycharm)


下一篇:CF 197A - Plate Game