【暑假】[实用数据结构]UVa11997 K Smallest Sums

UVa11997 K Smallest Sums

 题目:

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

------------------------------------------------------------------------------------------------------------------------------------------------------------------

思路:

 先思考2个有序表(sort后)AB合成的情况。组织如下

【 表】1: A1+B1 <=  A1+B2 <=  A1+B3 <=......

【表】2:A2+B1 <=  A2+B2 <=  A2+B3 <=......

......

【表】n:An+B1 <=  An+B2 <=  An+B3 <=......

转化为多路归并问题且有总数限制为k,因此将n个【表】合并为一个有序【表】C且表中数据数目为k。优先队列处理:初始化优先队列为n个表的第一元素,每次在队列中取出最小元素加入C并将该最小元素在【表】中的后一个元素入队。共取k个元素。

对于k个有序表的情况:两两合并。

于是有代码如下:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 5 using namespace std;
 6
 7 const int maxn = 800 + 10;
 8
 9 struct Node{
10     int s,b;
11     bool operator <(const Node& rhs) const{ //相反定义 <
12       return s>rhs.s;
13     }
14 };
15
16
17 void merge(int* A,int* B,int*C,int n){ //合并AB数组取其前n小的和放入C
18 priority_queue<Node> Q;
19   FOR(i,0,n) Q.push(Node{A[i]+B[0],0});
20   FOR(i,0,n){
21       Node u=Q.top();Q.pop();
22       C[i]=u.s;
23       int b=u.b;
24       if(b+1 < n) Q.push(Node{u.s-B[b]+B[b+1],b+1}); //加入A[a][b+1]
25   }
26 }
27
28 int main(){
29 int n;
30 int A[maxn],B[maxn];
31
32   while(scanf("%d",&n)==1){
33       FOR(j,0,n) scanf("%d",&A[j]); sort(A,A+n);
34       FOR(i,1,n){
35            FOR(j,0,n) scanf("%d",&B[j]);
36            sort(B,B+n);
37          merge(A,B,A,n);
38     }
39     printf("%d",A[0]);
40     FOR(i,1,n)
41       printf(" %d",A[i]);
42     printf("\n");
43  }
44  return 0;
45 }
时间: 2024-12-16 20:35:49

【暑假】[实用数据结构]UVa11997 K Smallest Sums的相关文章

uva11997 K Smallest Sums&amp;&amp;UVALive 3135 Argus(优先队列,多路归并)

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #include<stack> #in

题解——UVA11997 K Smallest Sums

题面 背景 输入 输出 翻译(渣自翻) 给定K个包含K个数字的表,要求将其能产生的\( k^{k} \)个值中最小的K个输出出来 题解 k路归并问题的经典问题 可以转化为二路归并问题求解 考虑A[],B[]两个有序数组 使用堆,记录一些二元组\( (x,y) \),x表示值,y表示对应的b的下标,因为我们是把b合并到a上,所以我们能够根据记录的下标推出后面的值 然后两两合并 所以就很简单 放代码 #include <cstdio> #include <algorithm> #inc

(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

UVA 11997 The K smallest Sums

给出K*K的矩阵,每一行取一个数,构成K个数的和,总共有 k^k种可能,从中取出前k个最小的. 一开始犯了错,因为只要对每行排序,最小的必定是第一列的和,然后我当时就想着,逐步推进,每次将某行的那个数变成其下一列那个数,当然间距要最小.我这样明显是不对的,这样的话每个数只用了一次,而题目的意思明显是可以重复多次. 然后大白上说的是把他看成两行,即每次处理两行,留下最小的k个 再与下一次读入的那一行继续处理.这个方法相当给力,不过有个难点是,怎么在两行的时候,比较快的得到前k小的,我试过全部算一遍

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

11997 - K Smallest Sums(优先队列)

11997 - K Smallest Sums You’re given k arrays, each array has k integers. There are kk ways to pick exactly one element in eacharray and calculate the sum of the integers. Your task is to find the k smallest sums among them.InputThere will be several

【优先队列之多路合并】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 思路 二路归并构建二维平面表:

D - K Smallest Sums(多路归并+贪心)

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 se

【优先队列】【UVa11997】K Smallest Sums

传送门 Description Input Output Translation · 给定k个长度为k的数组,把每个数组选一个元素加起来,这样共有kk种可能的答案,求最小的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 Hint k<=750 Solution 显然可以一行一行做,同时如果S+now[j]最小,需要S最小.即我们只需要记录前i行的最小的k个ans,分别与当前行的k个相加,从k2个an