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

UVA - 11997
K Smallest Sums
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 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 
#include 
#include 
#include 
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 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!


你可能感兴趣的:(UVa,OJ,数据结构:优先队列,算法的艺术)