(DS 《算法竞赛入门经典》)UVA 11997 K Smallest Sums

题目大意:有k个数组,每个数组选取一个数,组成k^k个数。在这k^k个数中选择最小的前k个数

解题思路:

1、如果只有k个数组,那么最后得到的最小的前k个数应该可以由前两个数组得到的最小k个数与第三个数组

按规则运算后得到。

2、如果每个数组只有3个数.那么前两个数组(a:(a0,a1,a2)    b:(b0,b1,b2,a与b数组都已经有序)运算后有的结果矩阵如下:

a0+b0,a0+b1,a0+b2

a1+b0,a1+b1,a1+b2

a2+b0,a2+b1,a2+b2

在这个矩阵中,a0+b0肯定是最小的。如果一个队列里只维持3个最小数,那么下一个产生最小数的位置是

a0+b1.分析如下:

由a1+b1>a1+b0可知,a1+b1及其后面的不可能产生下一个最小数.依照此逻辑可知下一个可能产生最小数的位置

是a0+b1

3、在以下的这种解法中,他并没有算出k^k个结果,它其实质算了n+n个可能产生最小数的结果而已

Problem K

K Smallest Sums

You‘re given k arrays, each array has k integers. There are kk ways to pick exactly one element in each array and calculate the sum of the integers. Your task is to find the k smallest sums among them.

Input

There will be several test cases. The first line of each case contains an integer k (2<=k<=750). Each of the following k lines contains k positive integers in each array. Each of these integers does not exceed 1,000,000. The input is terminated by end-of-file (EOF). The size of input file does not exceed 5MB.

Output

For each test case, print the k smallest sums, in ascending order.

Sample Input

3
1 8 5
9 2 5
10 7 6
2
1 1
1 2

Output for the Sample Input

9 10 12
2 2

Rujia Liu‘s Present 3: A Data Structure Contest Celebrating the 100th Anniversary of Tsinghua University
Special Thanks: Yiming Li
Note: Please make sure to test your program with the gift I/O files before submitting!

代码如下:

/*
 * UVA_11997.cpp
 *
 *  Created on: 2014年12月30日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>

using namespace std;

const int maxn = 758;
int A[maxn][maxn];

struct Item{
	int s,b;
	Item(int s,int b):s(s),b(b){

	}

	bool operator < (const Item& b) const{
		return s > b.s;
	}
};

void merge(int* A,int* B,int* C,int n){
	priority_queue<Item> q;

	int i;
	for(i = 0 ; i < n ; ++i){
		q.push(Item(A[i] + B[0],0));
	}

	for(i = 0 ; i < n ; ++i){
		Item item = q.top();
		q.pop();

		C[i] = item.s;
		int b = item.b;

		if(b+1 < n){
			q.push(Item(item.s - B[b] + B[b+1],b+1));
		}
	}
}

int main(){
	int n;

	while(scanf("%d",&n) == 1){
		int i;
		int j;

		for(i = 0 ; i < n ; ++i){
			for(j = 0 ; j < n ; ++j){
				scanf("%d",&A[i][j]);
			}

			sort(A[i],A[i]+n);
		}

		for(i = 1 ; i < n ; ++i){
			merge(A[0],A[i],A[0],n);
		}

		printf("%d",A[0][0]);

		for(i = 1 ; i < n ; ++i){
			printf(" %d",A[0][i]);
		}
		printf("\n");
	}

	return 0;
}
时间: 2024-10-03 21:54:35

(DS 《算法竞赛入门经典》)UVA 11997 K Smallest Sums的相关文章

【优先队列之多路合并】UVA - 11997 K Smallest Sums

Source : UVA - 11997 K Smallest Sums http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18702 题意 有k个整数数组,各包含k个元素,从每个数组中选取一个元素加起来,可以得到k^k个和,求这些和中最小的k个值. 示例 Sample Input 3 1 8 5 9 2 5 10 7 6 2 1 1 1 2 Sample Output 9 10 12 2 2 思路 二路归并构建二维平面表:

UVa 11997 K Smallest Sums 优先队列&amp;&amp;打有序表&amp;&amp;归并

UVA - 11997 K Smallest Sums Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status You're given k arrays, each array has k integers. There are k^k ways to pick exactly one element in each array and calculate the sum o

UVA 11997 K Smallest Sums 优先队列 多路合并

vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一道题,这道题的简化版其实在 15 年的广东省省赛出现过,当时是以送分题的形式出现的,可我还是没能做出来,归根到底还是看书不够,接触的题型不够多. *************************************************************大白书上的讲解开始*******

uva 11997 K smallest sums (优先队列 多路归并)

算法入门经典 训练指南 p189 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; struct Item { int s,b; Item(int s,int b) :s(s),b(b) {} bool operator < (const Item&rhs) co

AOAPC-I: 算法竞赛入门经典 UVa 习题集分类

数据结构基础 UVa 10004 二染色:二部图的判定.(bfs或dfs遍历的过程进行染色,看是否有冲突) UVa 10129 单词:有向图的欧拉道路. UVa 10054 项链:无向图的欧拉回路,首尾相接输出路径. UVa 10596 清晨漫步:无向图的欧拉回路. (对于欧拉道路或回路,在判断连通性等时注意先 if 下要访问的顶点是否出现.)

UVA 11997 K Smallest Sums 优先队列+归并 STL

题目链接: UVA...... 题目描述: 有K组数, 每组数有K个, 所以每组数各选一个加和有k^k种情况, 要求输出其中的最小的前k种, 从小到大输出 解题思路: 首先对于两个数组取前K个, 构造二元组(s, b) 其中s = Aa + Bb , a, b 为下标. 为什么不用三元组(s,a,b)呢, 因为二元组完全可以表示三元组, 下一个元素就是s+B[i+1]-B[i] . 我们需要把这k^2个和组织成如下k个有序表.(A, B是有序的哦) 表1:A1+B1<=A1+B2<=.....

uva 11997 K Smallest Sums 优先队列处理多路归并问题

题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<stack> 5 #include<queue> 6 #include<vector> 7 #include<map> 8 #includ

【UVA 11997 K Smallest Sums】优先级队列

来自<训练指南>优先级队列的例题. 题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18702 题意:给定k个整数数组,各包含k个元素.在每个数组中取一个元素加起来,可以得到kk个和,求这些和中最小的k个值(不去重). 数据范围:k [2, 750] 思路:暴力枚举k^k不可取. “先来看问题的简化版:给出两个长度为k的数组A和B,分别在A和B中任取一个数并相加,可以得到k^2个和,求这些和中最小的k个.” 首先

uva 11997 K Smallest Sums

首先对每行进行排序,并对与前两行有$A = a_1 \leq a_2 \leq \cdots \leq a_k$和$B = b_1 \leq b_2 \leq \cdots \leq b_k$.首先把所有的$b_i , i\in [1,k]$与$a_1$进行求和,并加入优先队列中.其中最小的必然是$a_1+b_1$,在优先队列队首.然后只需在优先队列中压入$a_1+b_2$,没有压入$a_2+b_1$原因是该和已经在队列中存在了,没有压入$a_2+b_2$的原因是$a_2+b_2 \leq a_