POJ2442 Sequence【k小堆问题】

来源:互联网 发布:网页棋牌游戏源码网 编辑:程序博客网 时间:2024/06/05 00:46

题目大意是:m行n列的一个数矩阵,每行抽一个数,可以同列,那么有n^m种sequence组合,在这些sequence中,找出:sequence和最小的n个sequence组合

方法:

当行数大于等于2行时候

       先比较第一行和第二行的和,把较小的放在第一行,把第一行压入优先队列

行数只有1行的时候,不进行该操作,直接把第一行的数压入优先队列(否则会造成第二行是0行和第一行交换后,把0行压入优先队列,wa掉)

 

对接下来的第2行到第m行

        先把优先队列输入到一个数组a里面,并把优先队列清空,a是从大到小的,那么接下来的遍历都是倒序遍历

        排序该行,然后该行第一个数和a中所有数相加压入优先队列

        对该行的第二个到第n个数每个数,和a里面每个数相加,如果比优先队列最大的元素小,那么弹出最大元素,压入该元素,比最大元素大,则break,跳到该行的下一个数

 

最后输出结果问题,最后一个数不要带空格,只能带回车符

#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>using namespace std;priority_queue<int>que;int m,n;int num[1111][2222];int a[2222];int main(){#ifndef ONLINE_JUDGEfreopen("G:/1.txt","r",stdin);freopen("G:/2.txt","w",stdout);#endifint T;scanf("%d",&T);while(T--){scanf("%d%d",&m,&n);for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){scanf("%d",&num[i][j]);}}if(m>=2)        {            int sum1=0,sum2=0;            for(int i=1;i<=n;i++)                sum1+=num[1][i];            for(int i=1;i<=n;i++)                sum2+=num[2][i];            if(sum1>sum2)                swap(num[1],num[2]);        }for(int i=1;i<=n;i++){que.push(num[1][i]);}for(int i=2;i<=m;i++){sort(num[i]+1,num[i]+1+n);for(int j=1;j<=n;j++){a[j]=que.top();que.pop();}for(int j=1;j<=n;j++){que.push(num[i][1]+a[j]);}for(int j=2;j<=n;j++){for(int k=n;k>=1;k--)if(num[i][j]+a[k]<que.top()){que.pop();que.push(num[i][j]+a[k]);}else{break;}}}for(int i=1;i<=n;i++){a[i]=que.top();que.pop();}for(int i=n;i>=2;i--){printf("%d ",a[i]);}printf("%d\n",a[1]);}}


 

0 0