UVA11997 K个最小和_优先队列&&K路合并

有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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值