UVa 11997 K Smallest Sums 优先队列&&打有序表&&归并

时间:2023-03-19 23:08:14
UVA - 11997
Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

Submit Status

You’re given k arrays, each array has k integers. There are k^k ways to pick exactly one element in each array and calculate the sum of the integers. Your task is to find the k smallest sums among them.

The question is from 

id=18702" style="color:rgb(255,153,0); text-decoration:none">here

.

My Solution

把每一个数组排序以后打个 有序表

表1: A1 + B1 <= A1+B2 <= A1+B3 <= ``````````

表2: A2 + B1 <= ``````

表3: A3 + B1 <= ``````

第啊张表里的元素形如 Aa + Bb。用(s = Aa+Bb, b) 表示,用s‘ = Aa + B(b+1) =Aa + Bb - Bb + B(b+1) = s - Bb + B(b+1);

#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 760;
int A[maxn],B[maxn]; struct Item {
int s, b;
Item(int s, int b): s(s), b(b) {}
bool operator < (const Item& rhs) const {
return s > rhs.s;
}
}; void merge_pro(int* A, int* b, int n)
{
priority_queue<Item> q;
for(int i = 0; i < n; i++)
q.push(Item(A[i]+B[0], 0));
for(int i = 0; i < n; i++){
Item item = q.top();q.pop();
A[i] = item.s;
int b = item.b;
if(b+1 < n) q.push(Item(item.s-B[b]+B[b+1], b+1)); //this "if" judge is really necessary!
}
} int main()
{
int n;
while(scanf("%d", &n) == 1){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(i == 0) scanf("%d", &A[j]);
else scanf("%d", &B[j]);
}
if(i == 0)sort(A, A+n);
else sort(B, B+n);
if(i != 0) merge_pro(A, B, n);
}
printf("%d", A[0]);
for(int i = 1; i < n; i++)
printf(" %d", A[i]);
printf("\n");
}
return 0;
}

Thank you!