poj 2442 priority_queue

http://poj.org/problem?id=2442

题意:略吐舌头

算法:想了好久还是只想到一半啊,先考虑只有两行的情况,有一种方法是暴力O(n^2) + O(n^2 * log(n^2)),就是把所有的可能都列举出来

这样的方法显然过于浪费,因为有很多值根本不用去求。

n log(n)的方法:可以先将暴力的方案写下来,假设两行为A 和 B ,则所有的方案为

A1+B1    A1+B2  A1+B3  A1+B4....    A1+Bn

A2+B1    A2+B2  A2+B3  A2+B4....    A2+Bn

............

An+B1    An+B2  An+B3  An+B4...    .An+Bn

上面第 i 行为Ai开始的所有方案,且每一行的第一个数都是最小的数(假设A B事先排好序)

从这个矩阵中取出前n小的数:,每行有一个指针,初始时都在1位置,先将第一列的数放进堆,取出最小的数,再将取出的数的那一行的指针后移一位,将移动到的位置山的数放入堆里,这样子连续取n次就可以了,这样子做的理由很简单,堆里面始终保存着n个元素,且这n个元素是分别包含A1 A2..An的最小的和,从这里面取一个数自然是当前最小的


两行搞定了,m行就是一样了,相当于每次处理两行即可,合并成一行当前答案,每读入一行再合并复杂度 m * n * log(n)。

#include <cstdio>
#include <cstring>
#include <set>
#include <string>
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <time.h>
#include <queue>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define sqr(x) ((x)*(x))
#define PB push_back
#define MP make_pair
#define foreach(it, x) for(typeof(x.begin()) it = x.begin(); it!=x.end();it++)
typedef unsigned long long ULL;
typedef long long lld;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int,int> PII;
const int maxn = 100010;
int ans[4012];
int tmp[4012];
int num[4012];
int pos[2012];
priority_queue<pair<int,int> > st;
int main() {
    int t,m,n;
    scanf("%d",&t);
    while(t--) 
    {
        scanf("%d%d",&m,&n);
        for(int i = 1 ; i <= n ; i++) scanf("%d",&ans[i]);
        sort(ans+1,ans+n+1);
        for(int i = 2 ; i <= m ; i++) 
        {
           for (int j = 1 ; j <= n ; j++)   scanf("%d",&num[j]),pos[j] = 1;
           sort(num+1 , num+n+1);
           while(!st.empty()) st.pop();
           for(int j=1;j<=n;j++) st.push( MP(-(ans[j] + num[1]) , j) ) ;
           int pt = 0;
           while(pt < n) 
           {
             pair<int,int> pr = st.top();
             st.pop();
             tmp[++pt] = - pr.first; 
             pos[pr.second] ++ ;
             st.push( MP(-(ans[pr.second]+num[pos[pr.second]]),pr.second) ) ;
           }
           for(int j = 1; j <= n ; j ++ )  ans[j] = tmp[j];
        }
        for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n ? '\n' : ' ');
    }
    return 0;
}



你可能感兴趣的:(poj 2442 priority_queue)