有K个整数数组,包含K个元素。在每个数组中取一个元素加起来,可以得到k^k个和。求这些和中最小的K个值
分析:这题有简化版本的,即2个整数数组A,B,包含K个元素,在每个数组中取一个元素加起来,可以得到k^2个和,求这些和中最小的K个值。
我们需要把这k^2个和组织成如下k个有序表.
表1:A1+B1<=A1+B2<=......<=A1+Bk
表2: A2+B1<=A2+B2<=......<=A2+Bk
表k:Ak+B1<=AK+B2<=......<=Ak+Bk
我们可以用二元组(s,b)来表示一个元素即s=Aa+Bb;为什么不保存A的下标a呢?因为我们用不到a的值。如果我们需要元素(s,b)在表a的下一个元素(s',b+1).只需要计算s'=s+B[b+1]-B[b];
这样我们先将K个表的第一个元素压入优先队列,这样队列中就用k个元素了。然后从队列中出一个值,就压入这个值所在表的下一个元素,直到k个值都出了优先队列。这样就得到k个最小值了。。
然后对与K个数组。我们只需两两合并即可。
#include <iostream>
#include <algorithm>
#include <queue>
#include <queue>
using namespace std;
const int MAX=770;
int store[MAX][MAX];
typedef struct _Node
{
int value;
int index;
bool operator <(const struct _Node a) const
{
return value>a.value;
}
}Node;
void Merge(int *a,int *b,int *c,int k)
{
priority_queue <Node> pq;
Node temp;
int i,j=0;
int sum;
int pos;
/*
a[1]+b[1], a[1]+b[2] ,a[1]+b[3], a[1]+b[k]
a[2]+b[1], a[2]+b[2] ,a[2]+b[3], a[2]+b[k]
a[3]+b[1], a[3]+b[2] ,a[3]+b[3], a[3]+b[k]
a[k]+b[1], a[k]+b[2] ,a[k]+b[3], a[k]+b[k]
如果给我们两个数组,让我们求前k个最小和则构建如上矩阵
这是一个k*k的矩阵,我们在求解过程中首先将前一列压入优先队列,然后取出顶部元素,找到其下标,如果下标是x,则代表x行的元素是其目前最小元素,我们将其后面的元素压入优先队列
*/
for(i=0;i<k;i++)
{
temp.value=a[i]+b[0];
temp.index=0;
pq.push(temp);
}
for(i=0;i<k;i++)
{
temp=pq.top();
pq.pop();
c[j++]=temp.value;
sum=temp.value;
pos=temp.index;
temp.value=sum+b[pos+1]-b[pos];
temp.index=pos+1;
pq.push(temp);
}
}
int main()
{
int k;
int i,j;
while(~scanf("%d",&k))
{
for(i=0;i<k;i++)
{
for(j=0;j<k;j++)
{
scanf("%d",&store[i][j]);
}
sort(store[i],store[i]+k);
}
for(i=1;i<k;i++)
{
Merge(store[0],store[i],store[0],k);
}
for(i=0;i<k;i++)
{
cout<<store[0][i]<<endl;
}
}
return 0;
}