2017年3月19日 | ljfcnyali
题目大意
m行n列的一个数矩阵,每行抽一个数,可以同列,那么有n^m种sequence组合,在这些sequence中,找出:sequence和最小的n个sequence组合。
Sample Input
1
2 3
1 2 3
2 2 3
1
2
3
4
1
2 3
1 2 3
2 2 3
Sample Output
3 3 4
1
3 3 4
题目分析
当行数大于等于2行时候,先比较第一行和第二行的和,把较小的放在第一行,把第一行压入优先队列
行数只有1行的时候,不进行该操作,直接把第一行的数压入优先队列(否则会造成第二行是0行和第一行交换后,把0行压入优先队列,wa掉)
对接下来的第2行到第m行
先把优先队列输入到一个数组a里面,并把优先队列清空,a是从大到小的,那么接下来的遍历都是倒序遍历
排序该行,然后该行第一个数和a中所有数相加压入优先队列
对该行的第二个到第n个数每个数,和a里面每个数相加,如果比优先队列最大的元素小,那么弹出最大元素,压入该元素,比最大元素大,则break,跳到该行的下一个数
AC代码
/*************************************************************************
> File Name: POJ2442.cpp
> Author: ljf-cnyali
> Mail: ljfcnyali@gmail.com
> Created Time: 2017-03-19 10:49:34
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
#define REP(i, a, b) for(int i = (a), _end_ = (b);i <= _end_; ++ i)
#define mem(a) memset((a), 0, sizeof(a))
#define str(a) strlen(a)
const int maxn = 10000;
priority_queue <int> Q;
int num[2000][maxn];
int a[maxn];
int n, m;
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T --) {
scanf("%d%d", &m, &n);
REP(i, 1, m)
REP(j, 1, n)
scanf("%d", &num[i][j]);
if(m >= 2) {
int sum1 = 0, sum2 = 0;
REP(i, 1, n)
sum1 += num[1][i];
REP(i, 1, n)
sum2 += num[2][i];
if(sum2 > sum1)
swap(num[1], num[2]);
}
REP(i, 1, n)
Q.push(num[1][i]);
REP(i, 2, m) {
sort(num[i] + 1, num[i] + n + 1);
REP(j, 1, n) {
a[j] = Q.top();
Q.pop();
}
REP(j, 1, n)
Q.push(num[i][1] + a[j]);
REP(j, 2, n)
for(int k = n; k >= 1; -- k)
if(num[i][j] + a[k] < Q.top()) {
Q.pop();
Q.push(num[i][j] + a[k]);
}
else
break ;
}
REP(i, 1, n) {
a[i] = Q.top();
Q.pop();
}
for(int i = n; i >= 2; -- i)
printf("%d ", a[i]);
printf("%d\n", a[1]);
}
return 0;
}