poj 2442 priority_queue

来源:互联网 发布:2016数控编程工资待遇 编辑:程序博客网 时间:2024/04/29 19:12

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;}



原创粉丝点击