看了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());
}
}
}