题意:给你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];
思想感觉就是DP。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 int a[800][800]; 8 int k; 9 int ans[800]; 10 struct Node{ 11 int s; 12 int id; 13 bool operator<(const Node a)const { 14 return s>a.s; 15 } 16 }; 17 void merge(int a[],int b[]){ 18 priority_queue<Node>Q; 19 for(int i=1;i<=k;i++){ 20 Node tt; 21 tt.s=a[i]+b[1]; 22 tt.id=1; 23 Q.push(tt); 24 } 25 for(int i=1;i<=k;i++){ 26 Node temp=Q.top(); 27 Q.pop(); 28 ans[i]=temp.s; 29 Node t2; 30 int num=temp.id; 31 if(num<k){ 32 t2.s=temp.s-b[num]+b[num+1]; 33 t2.id=num+1; 34 Q.push(t2); 35 } 36 } 37 } 38 int main(){ 39 while(~scanf("%d",&k)){ 40 memset(a,0,sizeof(a)); 41 memset(ans,0,sizeof(ans)); 42 for(int i=1;i<=k;i++){ 43 for(int j=1;j<=k;j++) 44 scanf("%d",&a[i][j]); 45 sort(a[i]+1,a[i]+k+1); 46 } 47 merge(a[1],a[2]); 48 for(int i=3;i<=k;i++) 49 merge(ans,a[i]); 50 for(int i=1;i<k;i++) 51 printf("%d ",ans[i]); 52 printf("%d ",ans[k]); 53 } 54 }