优先队列与堆

看了Sedgewick的红皮Algorithms中用堆实现优先队列后,在POJ上找了题目来练习下。

 

POJ2442题目大意:
    给出m个序列,每个序列有n个非负整数,每次从每一个序列中取出一个数(共m个数)求和(显然有 n^m 个和),求这些和数中前n个最小的数。

  样例:(第一行是测试次数1,第二行是m和n,接下来是m个序列)

Sample Input

  1
  2 3
  1 2 3
  2 2 3

  Sample Output

  3 3 4

实质上就是构造堆,为了保证堆中n个元素最小,外界元素如果有比堆顶元素大的,则交换,重新维护堆。

 

 


解题步骤:

1.将第一序列读入a数组中,并按升序排序。

2.将第二序列数据读入b数组中,

 

优先队列的代码:

    static class Heap {

        private int N;
        private int[] pq;

        public Heap(int n) {
            pq = new int[n + 1];
        }

        public int delMax() {                   //删除顶元
            int max = pq[1];
            pq[1] = pq[N--];
            sink(1);
            return max;
        }

        public int peek() {           
            return pq[1];
        }

        public void insert(int x) {             //插入元素
            pq[++N] = x;
            swim(N);
        }

        public void swim(int n) {                   //上浮
            while (n / 2 >= 1 && pq[n / 2] < pq[n]) {
                int t = pq[n / 2];
                pq[n / 2] = pq[n];
                pq[n] = t;
                n = n / 2;
            }
        }

        public void sink(int n) {                //下沉
            while (2 * n <= N) {
                int j = 2 * n;
                if (j < N && pq[j + 1] > pq[j]) {
                    j++;
                }
                if (pq[n] >= pq[j]) {
                    break;
                }
                int t = pq[n];
                pq[n] = pq[j];
                pq[j] = t;
                n=j;
            }

        }

        public boolean isEmpty() {
            return N == 0;
        }
    }

 

 

 

 

 

java AC代码:

 

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

/**
 *
 * @author Administrator
 */
public class Main2442 {

    static class Heap {

        private int N;
        private int[] pq;

        public Heap(int n) {
            pq = new int[n + 1];
        }

        public int delMax() {
            int max = pq[1];
            pq[1] = pq[N--];
            sink(1);
            return max;
        }

        public int peek() {
            return pq[1];
        }

        public void insert(int x) {
            pq[++N] = x;
            swim(N);
        }

        public void swim(int n) {
            while (n / 2 >= 1 && pq[n / 2] < pq[n]) {
                int t = pq[n / 2];
                pq[n / 2] = pq[n];
                pq[n] = t;
                n = n / 2;
            }
        }

        public void sink(int n) {
            while (2 * n <= N) {
                int j = 2 * n;
                if (j < N && pq[j + 1] > pq[j]) {
                    j++;
                }
                if (pq[n] >= pq[j]) {
                    break;
                }
                int t = pq[n];
                pq[n] = pq[j];
                pq[j] = t;
                n=j;
            }

        }

        public boolean isEmpty() {
            return N == 0;
        }
    }

    public static void main(String[] args) {
//        test();
        Scanner scan = new Scanner(System.in);
        int count = scan.nextInt();
        while (count-- != 0) {
            int num = scan.nextInt();
            int n = scan.nextInt();
            int[] a = new int[n + 1];
            int[] b = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                a[i] = scan.nextInt();
            }
            Arrays.sort(a);
            while (--num != 0) {
                for (int i = 1; i <= n; i++) {
                    b[i] = scan.nextInt();
                }

                Arrays.sort(b);
                Main2442.Heap heap = new Heap(n);

                for (int i = 1; i <= n; i++) {
                    heap.insert(a[i] + b[1]);
                }
                for (int i = 2; i <= n; i++) {
                    for (int j = 1; j <= n; j++) {
                        if (heap.peek() > b[i] + a[j]) {
                            heap.delMax();
                            heap.insert(b[i] + a[j]);
                        } else {
                            break;         //后面就不用比较了
                        }
                    }
                }
                for (int i = n; i >= 1; i--) {
                    a[i] = heap.delMax();
                }
            }

            for (int i = 1; i <= n - 1; i++) {
                System.out.print(a[i] + " ");
            }
            System.out.println(a[n]);

        }
    }

    public static void test() {
        Scanner scan = new Scanner(System.in);
        int m = scan.nextInt();
        Main2442.Heap heap = new Heap(m);
        for (int i = 0; i < m; i++) {
            int x = scan.nextInt();
            heap.insert(x);
        }
        while (!heap.isEmpty()) {
            System.out.println(heap.delMax());
        }


    }
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值