P1392 取数

P1392 取数

题目描述

在一个n行m列的数阵中,你须在每一行取一个数(共n个数),并将它们相加得到一个和。对于给定的数阵,请你输出和前k小的取数方法。
说明

对于20%的数据,n≤8

对于100%的数据,n≤800,k≤m≤800

Solution

先看一下当 \(n == 2\) 时的序列合并
类似的,我们先把第一行和第二行合并, 记为序列 \(temp[\ ]\)
因为每次丢进堆中的都是 \(a[x] + b[y]\)
所以最终会得到的 \(temp[\ ]\) 序列为 有序的序列且每个元素都形如\(a[x] + b[y]\)
如此, 我们在将此序列和下一个序列 \(c\) 合并
可以得到一个有序序列
此序列有序且每个元素都形如 \(temp[x] + c[y]\)\(a[x] +b[y] + c[z]\)
故我们将序列合并 \(n - 1\) 次, 每次取新序列前 \(K\) 项, 最后大融合的序列即为答案

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 919;
int lenx, leny, K;
//int map[maxn][maxn];
int a[maxn], b[maxn];
int temp[maxn];
struct Node{
	int val, i, j;
	bool operator < (const Node &a)const{
		return val < a.val;
		}
	};
int main(){
	lenx = RD(), leny = RD(), K = RD();
	REP(i, 1, leny)a[i] = RD();
	sort(a + 1, a + 1 + leny);//处理第一行
	REP(t, 2, lenx){
		priority_queue<Node>Q;
		REP(i, 1, leny)b[i] = RD();
		sort(b + 1, b + 1 + leny);//读入新一行
		REP(i, 1, K)Q.push((Node){-(a[i] + b[1]), i, 1});
		int i = 0;
		while(++i <= K){
			Node top = Q.top();Q.pop();
			temp[i] = -(top.val);
			Q.push((Node){-(a[top.i] + b[top.j + 1]), top.i, top.j + 1});
			}
		REP(i, 1, K)a[i] = temp[i];
		}
	REP(i, 1, K)printf("%d ", a[i]);
	puts("");
	return 0;
	}
posted @ 2018-10-16 11:10  Tony_Double_Sky  阅读(242)  评论(0编辑  收藏  举报