1 条题解

  • 3
    @ 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
上传者