题意:给出一个k*k的矩阵,要求在每一行中取出一个数,让这k个数相加,求和最小的k个数
思路:只需要把表两两相加即可,每次只保留前面的k个最小的数和下个表进行运算即可。
用一个二元组(s,b)表示s=A[a]+B[b], s`=A[a]+B[b+1]=A[a]+B[b]-B[b]+B[b+1]=s-B[b]+B[b+1];
s是记录A表和B表的和,b记录加的是B中值的下标,方便下次减去B[b],加上B[b+1]
#include<stdio.h>
#include<queue>
#include<algorithm>
#define N 760
using namespace std;
int A[N][N];
struct node
{
int s, b;
node(int s,int b):s(s),b(b) {}
bool operator <(const node &A) const
{
return A.s<s;
}
};
void merge(int *A,int *B,int *C,int n)
{
priority_queue<node>Q;
for(int i=0; i<n; i++)
Q.push(node(A[i]+B[0],0));
for(int i=0; i<n; i++)
{
node temp=Q.top();
Q.pop();
C[i]=temp.s;
int b=temp.b;
Q.push(node(temp.s-B[b]+B[b+1],b+1));
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
scanf("%d",&A[i][j]);
sort(A[i],A[i]+n);
}
for(int i=1; i<n; i++)
{
//两个表累加,把前k小和记录到A[0]中
merge(A[0],A[i],A[0],n);
}
printf("%d",A[0][0]);
for(int i=1; i<n; i++)
printf(" %d",A[0][i]);
printf("\n");
}
return 0;
}