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++ ,