课程作业的Online Judge有一道算法题:
Description
The mall is running a T-day promotion.
·Every day, customers who shop at the mall can put their own receipts into a box to participate in the promotion.
·Every day after the mall closes, the manager will take out the receipt with the maximum amount in the box and the lucky customer’s spending WILL BE PAID BY THE MALL.
·If there are more than one maximums in the box, only one of them can be selected randomly.
·Every day the rest receipts will remain in the event box until the end of the promotion.
·Test data promise the box will never be empty during these days.
We need your help to figure out how much the mall pay for the promotion.
Input
The first line contains an integer T, 1 ≤ T ≤ 100,000, the number of days of the promotion.
Each of the following T lines contains a sequence of non-negative integers separated by whitespace.
The numbers in the (i+1)-st line give the data for the i-th day.
The first number in each of these lines, n, 0 ≤ n ≤ 50, is the number of receipts and the subsequent n numbers are positive integers of the bill amounts.
No receipt is bigger than 50,000.
Output
The total amount paid to the customers.
Sample Input 1
5
3 1 2 2
2 1 1
4 10 5 5 1
0
1 2
Sample Output 1
24
做题的过程中犯了一些错误:
int left = k * 2 + 1;//左孩子
int right = k *2 + 2;//右孩子
int parent = (k - 1)/2;//父母
void HeapAdjust(int* a, int heap_size, int k)
//假设指标为k 的根节点下面的已经是最大堆,但k节点自己小于其孩子,对此进行调整
{
int left = k * 2 + 1;//左孩子
int right = k * 2+2;//右孩子
int l,tmp;
l=k;
if (left<heap_size && a[left]>a[k]) {
l = left;
}
if (right<heap_size && a[right]>a[k]) {
l = right; //这里错了
}
if (l != k) {
tmp = a[k];
a[k] = a[l];
a[l] = tmp;
HeapAdjust(a, heap_size,l);
}
}
正确的:
void HeapAdjust(int* a, int heap_size, int k)
//假设指标为k 的根节点下面的已经是最大堆,但k节点自己小于其孩子,对此进行调整
{
int left = k * 2 + 1;//左孩子
int right = k * 2+2;//右孩子
int l,tmp;
l=k;
if (left<heap_size && a[left]>a[k]) {
l = left;
}
if (right<heap_size && a[right]>a[l]) {
l = right; //这才对了
}
if (l != k) {
tmp = a[k];
a[k] = a[l];
a[l] = tmp;
HeapAdjust(a, heap_size,l);
}
}
我在OJ系统上提交的代码:
#include
#include
//以下的堆,都是最大堆,数组从0开始
void HeapInsert(int a[], int heap_size, int key);
void HeapAdjust(int* a, int heap_size, int k);
void HeapBuild(int* a, int heap_size);
int HeapMax(int* a, int heap_size);
void HeapInsert(int a[], int heap_size, int key)
//heap_size是没有插入之前堆的大小,插入之后也不改变,要手动加1
{
int k = heap_size;
while (k > 0 ) {
if((k-1)/2<0) break;
if(a[(k - 1) / 2] >= key) break;
a[k] = a[(k - 1) / 2];
k = (k - 1) / 2;
}
a[k] = key;
}
void HeapAdjust(int* a, int heap_size, int k)
//假设指标为k 的根节点下面的已经是最大堆,但k节点自己小于其孩子,对此进行调整
{
int left = k * 2 + 1;//左孩子
int right = k * 2+2;//右孩子
int l,tmp;
l=k;
if (left<heap_size && a[left]>a[k]) {
l = left;
}
if (right<heap_size && a[right]>a[l]) {
l = right;
}
if (l != k) {
tmp = a[k];
a[k] = a[l];
a[l] = tmp;
HeapAdjust(a, heap_size,l);
}
}
void HeapBuild(int* a, int heap_size)
//建堆
{
//从底层开始维护,k的父母是(k-1)/2向下取整,堆的最后一个元素的父母是heapsize/2-1
for (int i = heap_size / 2 - 1; i >= 0; i--) {
HeapAdjust(a, heap_size, i);
}
}
int HeapMax(int* a, int heap_size)
//取出最大的元素,也就是根结点,然后维护成最大堆
{
int max;
max = a[0];
a[0] = a[heap_size - 1];
HeapAdjust(a, heap_size-1, 0);
return max;
}
int main()
{
int T, n,key, size=0,i,j;//size为目前累计账单数,也就是heap_size
long sum = 0;//获奖账单累计金额
static int a[50000000]={0};
scanf("%d", &T);
//先用第一组数据建一个最大堆
scanf("%d", &n);
for ( i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
size = n;
HeapBuild(a, size);
sum += HeapMax(a, size);
size--;
for ( i = 1; i < T; i++) {
scanf("%d", &n);
for ( j = 0; j < n; j++) {
scanf("%d", &key);
HeapInsert(a, size, key);
size++;
}
sum += HeapMax(a, size);
size--;
}
printf("%ld\n", sum);
return 0;
}
不知道为什么,我把这段代码复制粘贴到vc++6.0,然后用助教给的数据测试,答案是错的。反正OJ系统 Accept 就行,以后再看。这样一个问题竟然做了两三天,真头大,继续加油 !
(写代码时参考了:https://www.cnblogs.com/Nastukashii/p/4394307.html)