1 条题解
-
3yejun LV 10 MOD @ 2019-01-08 21:05:54
/* 考虑只有两个序列的情况,记序列为A和B 用优先队列维护每个序列(小根堆) 显然最小值是两个序列的最小值的和,即A[1]+B[1] 次小值为min{A[1]+B[2],A[2]+B[1]} 也就是说,确定A[i]+B[j]为第k小的和后,第k+1小的和是min{A[i+1]+B[j],A[i]+B[j+1],其他情况} 换句话说,确定A[i]+B[j]为第k小的和后,A[i+1]+B[j]和A[i]+B[j+1]就进入了备选答案 需要注意的是A[1]+B[2]和A[2]+B[1]都会产生备选答案A[2]+B[2]所以在小根堆中维护一个三元组(i,j,flag) flag表示上一次移动的是否是j,用于限制j不可以连续增加而产生冗余的备选答案 于是,我们这样做可以得到两个序列的前n小的和 由数学归纳法可知,将两个序列的前n小的和变成一个新的序列,继续与下个序列操作,依次操作至只剩一个序列后,这个序列里的前n个数,就是前n小的和 */ #define method_1 #ifdef method_1 /* */ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<stack> #include<vector> #include<cstring> #include<cstdlib> using namespace std; typedef long long ll; const int maxn=2000+5; const int INF=0x3f3f3f3f; int t,n,m,a[maxn][maxn],b[maxn]; struct node{ int c,d,i,j; bool f; node(){}; node(int a1, int a2, int a3, int a4, bool a5) { c = a1, d = a2, i = a3, j = a4, f=a5; } }; bool operator < (const node& a, const node& b) { return (a.c + a.d) > (b.c + b.d); //小根堆优先队列大于小于号要反过来 } priority_queue<node>q; void cal(int x,int y){ int pos=0,cnt=0; while(!q.empty()) q.pop(); q.push(node(a[x][1],a[y][1],1,1,false)); // b[++pos]=a[x][1]+a[y][1]; while(++cnt<=n){ node temp=q.top(); q.pop(); b[++pos]=temp.c+temp.d; if(temp.f==false&&temp.i<n){ q.push(node(a[x][temp.i+1],a[y][temp.j],temp.i+1,temp.j,false)); } if(temp.j<n) q.push(node(a[x][temp.i],a[y][temp.j+1],temp.i,temp.j+1,true)); } // memcpy(a[y],b,sizeof(b)); for(int i=1;i<=n;i++){ a[y][i]=b[i]; // cout<<b[i]<<" "; } // cout<<endl; } int main() { ios::sync_with_stdio(false); cin>>t; while(t--){ cin>>m>>n; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ cin>>a[i][j]; } sort(a[i]+1,a[i]+n+1); } for(int i=2;i<=m;i++){ cal(i-1,i); } for(int i=1;i<=n;i++){ cout<<a[m][i]<<" "; } cout<<endl; /* for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ cout<<a[i][j]<<" "; } cout<<endl; } */ } return 0; } #endif #ifdef method_2 /* */ #endif #ifdef method_3 /* */ #endif
- 1
信息
- 难度
- 5
- 分类
- (无)
- 标签
- (无)
- 递交数
- 39
- 已通过
- 13
- 通过率
- 33%
- 被复制
- 3
- 上传者