Java解法,贪心算法与区间合并的一道好题

To Fill or Not to Fill

http://www.nowcoder.com/questionTerminal/f7eba38f7cd24c45982831e0f38518f9

本题解思路来源于其他人的题解,在他的基础上进行了优化。
先提供一份他人的题解,我将其翻译成了java语言版本。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int c = scanner.nextInt();
        int d = scanner.nextInt();
        int avg = scanner.nextInt();
        int n = scanner.nextInt();
        List<Pair> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            double price = scanner.nextDouble();
            int distance = scanner.nextInt();
            list.add(new Pair(price,distance));
        }
        list.sort(Comparator.comparing(a -> a.price));
        boolean[] visited = new boolean[d];
        int maxDistance = c * avg;
        double cost = 0.0;
        for (int i = 0; i < n; i++) {
            Pair pair = list.get(i);
            int need = (pair.distance+maxDistance < d ? maxDistance : d - pair.distance);
            int cnt = 0;
            for (int j = pair.distance; j < pair.distance+need; j++) {
                if (!visited[j]){
                    visited[j] = true;
                    cnt++;
                }
            }
            cost += cnt/(avg*1.0)*pair.price;
        }
        int i;
        for (i = 0; i < d; i++) {
            if (!visited[i]){
                System.out.printf("The maximum travel distance = %.2f\n",(double)i);
                break;
            }
        }
        if (i == d)
            System.out.printf("%.2f\n",cost);

    }
}
class Pair{
    Double price;
    int distance;
    public Pair(Double price, int distance) {
        this.price = price;
        this.distance = distance;
    }
}

上面的题解逻辑清晰,使用visited数组也非常巧妙,基本上不需要注释也能理解。但是存在的问题是visited数组本身空间代价比较高,当距离较大时,无论是时间复杂度和空间复杂度都会有很大的开销。
实际上visited数组有用的部分主要是两个端点距离,即begin和end,中间的数据意义并不大。在此思路上进行优化,只存储两个区间端点,维护一个不相交的区间,产生新的区间后将区间进行合并。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int c = scanner.nextInt();
        int d = scanner.nextInt();
        int avg = scanner.nextInt();
        int n = scanner.nextInt();
        List<Pair> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            double price = scanner.nextDouble();
            int distance = scanner.nextInt();
            list.add(new Pair(price,distance));
        }
        list.sort(Comparator.comparing(a -> a.price));
        int maxDistance = c * avg;
        double cost = 0.0;
        Queue<Interval> queue = new PriorityQueue<>(Comparator.comparingInt(a->a.start));
        for (int i = 0; i < n; i++) {
            Pair pair = list.get(i);
            int need = (pair.distance+maxDistance < d ? maxDistance : d - pair.distance);
            int cnt = 0;
            Interval interval = new Interval(pair.distance,pair.distance+need);
            int len = 0;
            Iterator<Interval> iterator = queue.iterator();
            while (iterator.hasNext()){
                Interval cur = iterator.next();
                len += cur.end - cur.start;
                if (cur.start <= interval.end && cur.end >= interval.start){ //区间相交
                    iterator.remove();
                    int min = Math.min(cur.start,interval.start);
                    int max = Math.max(cur.end,interval.end);
                    interval = new Interval(min,max); //区间合并
                }
            }
            queue.offer(interval);
            int afterLen = 0;
            for (Interval next : queue) {
                afterLen += next.end - next.start;
            }
            cnt += afterLen - len; //前后区间差值即为加油量
            cost += cnt/(avg*1.0)*pair.price;
        }
        Interval interval = queue.poll(); //最后能行进的区间范围
        assert interval != null;
        if (interval.start == 0 && interval.end == d){
            System.out.printf("%.2f\n",cost);
        }else {
            System.out.printf("The maximum travel distance = %.2f\n",(double)interval.end);
        }
    }
}
class Pair{
    Double price;
    int distance;
    public Pair(Double price, int distance) {
        this.price = price;
        this.distance = distance;
    }
}
class Interval{
    int start;
    int end;
    public Interval(int start, int end) {
        this.start = start;
        this.end = end;
    }
}
全部评论

相关推荐

02-11 12:20
门头沟学院 Java
面试中的青提很胆小:我不信有比我们学校更逆天的,计算机专业就业第一位是我们学校二餐厅的打印店
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
牛客网
牛客企业服务