acwing 算法基础-贪心

耍杂技的牛

农民约翰的N头奶牛(编号为1…N)计划逃跑并加入马戏团,为此它们决定练习表演杂技。

奶牛们不是非常有创意,只提出了一个杂技表演:

叠罗汉,表演时,奶牛们站在彼此的身上,形成一个高高的垂直堆叠。

奶牛们正在试图找到自己在这个堆叠中应该所处的位置顺序。

这N头奶牛中的每一头都有着自己的重量Wi以及自己的强壮程度Si。

一头牛支撑不住的可能性取决于它头上所有牛的总重量(不包括它自己)减去它的身体强壮程度的值,现在称该数值为风险值,风险值越大,这只牛撑不住的可能性越高。

您的任务是确定奶牛的排序,使得所有奶牛的风险值中的最大值尽可能的小。

输入格式
第一行输入整数N,表示奶牛数量。

接下来N行,每行输入两个整数,表示牛的重量和强壮程度,第i行表示第i头牛的重量Wi以及它的强壮程度Si。

输出格式
输出一个整数,表示最大风险值的最小可能值。

数据范围
1≤N≤50000,
1≤Wi≤10,000,
1≤Si≤1,000,000,000
输入样例:
3
10 3
2 5
3 3
输出样例:
2
代码:

import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Node[] nodes = new Node[n+5];
        for(int i=0;i<n;i++){
            int w = sc.nextInt();
            int s = sc.nextInt();
            nodes[i] = new Node(w,s);
        }
        Arrays.sort(nodes,0,n);
        int sum = 0;
        int res = Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            res = Math.max(res,sum-nodes[i].s);
            sum += nodes[i].w;
        }
        System.out.println(res);
    }
}
class Node implements Comparable<Node>{
    int w,s,sum;

    public Node(int w, int s) {
        this.w = w;
        this.s = s;
        this.sum = w+s;
    }

    @Override
    public int compareTo(Node o) {
        return this.sum-o.sum;
    }
}

区间选点

给定N个闭区间[ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。

输出选择的点的最小数量。

位于区间端点上的点也算作区间内。

输入格式
第一行包含整数N,表示区间数。

接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。

输出格式
输出一个整数,表示所需的点的最小数量。

数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例
3
-1 1
2 4
3 5
输出样例
2

思路:
按照区间左端点排序,每次判断当前区间是否包含在上次选择的dis以内。
如果不在,那么必然要在此区间中选择一个点,我们将dis赋值为当前区间的右端点。
如果在,为了确保每个区间都被选择过一个点。我们需要令dis = min(dis,nodes[i].r);这样可以确保所有的区间都被选择过一个点。
代码

import java.util.Arrays;
import java.util.Scanner;

public class Main{
    static int n;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        Node[] nodes = new Node[n+5];
        for(int i=0;i<n;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            nodes[i] = new Node(a,b);
        }
        Arrays.sort(nodes,0,n);
        int res = 0;
        int dis = Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            if(nodes[i].l>dis) {
                res++;
                dis = nodes[i].r;
            }else{
                dis = Math.min(dis,nodes[i].r);
            }
        }
        System.out.println(res);
    }
}
class Node implements Comparable<Node>{
    int l,r;

    public Node(int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Node o) {//按照左端点排序
        return this.l-o.l;
    }
}

最大不相交区间数量

给定N个闭区间[ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。

输出可选取区间的最大数量。

输入格式
第一行包含整数N,表示区间数。

接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。

输出格式
输出一个整数,表示可选取区间的最大数量。

数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例
3
-1 1
2 4
3 5
输出样例:
2
思路
在n个区间中选择若干个互不相交的区间,我们可以将区间按照右端点排序,每次判断当前区间是否和dis有交点,没有交点时,我们选择当前区间。
代码

import java.util.Arrays;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Node[] nodes = new Node[n+5];
        for(int i=0;i<n;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            nodes[i] = new Node(a,b);
        }
        Arrays.sort(nodes,0,n);
        int res = 0;
        int dis = Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            if(dis<nodes[i].l){
                res ++;
                dis = nodes[i].r;
            }
        }
        System.out.println(res);
    }
}
class Node implements Comparable<Node>{
    int l,r;

    public Node(int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Node o) {
        return this.r-o.r;
    }
}

区间分组

给定N个闭区间[ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。

输入格式
第一行包含整数N,表示区间数。

接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。

输出格式
输出一个整数,表示最小组数。

数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例
3
-1 1
2 4
3 5
输出样例:
2
思路:

代码

import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Node[] nodes = new Node[n+5];
        for(int i=0;i<n;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            nodes[i] = new Node(a,b);
        }
        Arrays.sort(nodes,0,n,new Ok());
        PriorityQueue<Node> queue = new PriorityQueue<>();
        for(int i=0;i<n;i++){
            if(queue.size()==0||queue.peek().r>=nodes[i].l){
                queue.add(nodes[i]);
            }else{
                queue.poll();
                queue.add(nodes[i]);
            }
        }
        System.out.println(queue.size());
    }
}
class Ok implements Comparator<Node> {

    @Override
    public int compare(Node o1, Node o2) {
        return o1.l-o2.l;
    }
}
class Node implements Comparable<Node>{
    int l,r;

    public Node(int l, int r) {
        this.l = l;
        this.r = r;
    }

    @Override
    public int compareTo(Node o) { //按照右端点排序
        return this.r-o.r;
    }
}

区间覆盖

给定N个闭区间[ai,bi]以及一个线段区间[s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出-1。

输入格式
第一行包含两个整数s和t,表示给定线段区间的两个端点。

第二行包含整数N,表示给定区间数。

接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。

输出格式
输出一个整数,表示所需最少区间数。

如果无解,则输出-1。

数据范围
1≤N≤105,
−109≤ai≤bi≤109,
−109≤s≤t≤109
输入样例
1 5
3
-1 3
2 4
3 5
输出样例:
2

代码:

import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int s = sc.nextInt();
        int t = sc.nextInt();
        int n = sc.nextInt();
        Node[] nodes = new Node[n+5];
        for(int i=0;i<n;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            nodes[i] = new Node(a,b);
        }
        Arrays.sort(nodes,0,n);
        int dis = s;
        int res = 0;
        for(int i=0;i<n;i++){
            if(nodes[i].l>dis){
                System.out.println("-1");
                return;
            }else{
                res ++;
                int temp = dis;
                while(i<n&&nodes[i].l<=dis){
                    temp = Math.max(temp,nodes[i].r);
                    i++;
                }
                dis = temp;
                i--;
            }
            if(dis>=t) break;
        }
        if(dis<t) System.out.println("-1");
        else System.out.println(res);
    }
}
class Node implements Comparable<Node>{
    int l,r;
    public Node(int l, int r) {
        this.l = l;
        this.r = r;
    }
    @Override
    public int compareTo(Node o) {
        return this.l-o.l;
    }
}
posted @ 2020-12-04 22:48  键盘_书生  阅读(45)  评论(0编辑  收藏  举报