当前位置:编程学习 > C/C++ >>

UVa - 11997 - K Smallest Sums

题意:输入一个数k(2 <= k <= 750),然后输入k*k的矩阵,元素为不超过1,000,000的正整数,k行每行取一个数出来相加,求最小的前k个和。
 
 
 
——>>k个数的和最小,那么任意两行的那两个数的和也最小,否则就可以找到比该值更小的数,所以,可以先求两行中k个最小和,再进行多路归并即可。
 
[cpp]  
#include <iostream>  
#include <algorithm>  
#include <queue>  
  
using namespace std;  
  
const int maxn = 750 + 10;      //每行最多可能有750个数  
  
struct Item     //定义结点类型  
{  
    int s;      //s = A[i] + B[j]  
    int b;      //b = j即B[j]的下标  
    Item(int ss, int bb):s(ss), b(bb){}  
    bool operator < (const Item& e) const       //重载运算符,使优先队列中的元素按s的值从小到大地排  
    {  
        return s > e.s;  
    }  
};  
  
void merge(int *A, int *B, int k)       //将表A与表B合并,即求当k = 2时的k个最小和  
{  
    int i;  
    priority_queue<Item> pq;  
    for(i = 0; i < k; i++)      //第一列元素入列  
        pq.push(Item(A[i]+B[0], 0));  
    for(i = 0; i < k; i++)      //找出k个最小和  
    {  
        Item item = pq.top();       //取出队列中最小的  
        pq.pop();  
        A[i] = item.s;  
        int b = item.b;  
        if(b+1 < k)     //如果不是最后一个,就加入第“1”列的行列中去  
            pq.push(Item(item.s-B[b]+B[b+1], b+1));  
    }  
}  
  
int a[maxn][maxn];      //输入的k*k数组  
int main()  
{  
    int k, i, j;  
    while(cin>>k)  
    {  
        for(i = 0; i < k; i++)  
        {  
            for(j = 0; j < k; j++)  
                cin>>a[i][j];  
            sort(a[i], a[i]+k);     //排个序  
        }  
        for(i = 1; i < k; i++)  
            merge(a[0], a[i], k);       //两两合并  
        for(i = 0; i < k-1; i++)        //输出结果  
            cout<<a[0][i]<<" ";  
        cout<<a[0][k-1]<<endl;  
    }  
    return 0;  
}  
 
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,