题目:https://uva.onlinejudge.org/external/119/11997.pdf
对于两组数a[n],b[n],每组长度为n,现在要得到a[i]+b[j] (1<=i,j<=n)的和 中前n小的值。
先对b[n]排序
方法是利用b[1] + x<b[2]+x<...<b[n]+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a[n]+b[1]);
弄出n个指针p[i],分别表示队列里a[i]加上的是b[p[i] ];
每次取出队头,删去,然后补上一个新的元素。
比如取出 a[i]+b[p[i] ]
那么得到一个答案a[i]+b[p[i] ],然后放入a[i]+b[p[i] +1];
进行n次,那么可以得到前n小的数
变式:
对于两组数a[n],b[m],现在要得到a[i]+b[j] (1<=i<=n,1<=j<=m)的和 中前k小的值。
先对b[m]排序
方法是利用b[1] + x<b[2]+x<...b[m]+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a[n]+b[1]);
弄出n个指针p[i],分别表示队列里a[i]加上的是b[p[i] ];
每次取出队头,删去,然后补上一个新的元素。
比如取出 a[i]+b[p[i] ]
那么得到一个答案a[i]+b[p[i] ],然后放入a[i]+b[p[i] +1];
进行k次,那么可以得到前k小的数
变式:
有n组数,每组数取一个数相加 得到一个结果,要求前k小的结果分别是多少。
对于每两组数,用到的一定是这两组数中(分别取1个数,他们的 和中)最小的k个数,
故将这两组变成了一组,减少了组数,依此类推,直到最后剩下一组(长度为k)
const int INF =0x3f3f3f3f;
const int maxn= 760 ;
//const int maxm= ;
//by yskysker123
int n,a[maxn][maxn];
int p[maxn];
struct Node
{
int num,index;
Node(){}
Node(int num,int index):num(num),index(index){}
};
struct cmp
{
bool operator()(Node x,Node y )
{
return x.num>y.num;
}
};
void merge(int le,int ri)
{
priority_queue<Node,vector<Node > ,cmp> q;
for(int i=1;i<=n;i++)
{
p[i]=1;
q.push( Node( a[le][i]+a[ri][1],i) );
}
for(int ii=1;ii<= n ;ii++)
{
Node tmp=q.top();q.pop();
int index=tmp.index;
int num=tmp.num;
a[le][ii]=num ;
p[index]++;
if(p[index]<=n )
q.push(Node (num-a[ri][p[index]-1 ]+a[ri][p[index] ] ,index ) );
}
}
int main()
{
int x;
while(~scanf("%d",&n)) //有一种错误叫做忘写~或!=EOF,这种错误常常是由于移动代码时造成的,通常还会在事先
{ //表现为 () 内有;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
sort(a[i]+1,a[i]+1+n);
}
for(int i=2;i<=n;i++)
{
merge(1,i );
}
for(int i=1;i<n ;i++)
printf("%d ",a[1][i]);
printf("%d\n",a[1][n]);
}
return 0;
}
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
#include<utility>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI 3.1415926535897932384626
#define eps 1e-10
#define sqr(x) ((x)*(x))
#define FOR0(i,n) for(int i=0 ;i<(n) ;i++)
#define FOR1(i,n) for(int i=1 ;i<=(n) ;i++)
#define FORD(i,n) for(int i=(n) ;i>=0 ;i--)
#define lson num<<1,le,mid
#define rson num<<1|1,mid+1,ri
#define MID int mid=(le+ri)>>1
#define zero(x)((x>0? x:-x)<1e-15)
#define mk make_pair
#define _f first
#define _s second
using namespace std;
//const int INF= ;
typedef long long ll;
//const ll inf =1000000000000000;//1e15;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);