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 题目大意:
给定一个k*k的一个矩阵,如果让你在每一行取出一个数,再将每一行取出的数相加,那么总共可以得到k^k种相加方法,现在让你求出这k^k个结果中最小的k个结果。 分析:
咋一看,的确很难有想法,但是仔细分析这个题目我们会发现其实这个问题是满足最优子结构的,比如:
如果我们已经计算出了前m行,每行取出一个数相加的最小的k个结果,分别是DP[1],DP[2]...DP[k](注意这里的DP表示的是前m行每行一个相加的最小的前k个值)
假设第m+1行的值是A[1],A[2]...A[k] (注意这里的A[i]表示的是第m+1行的第i个数)
当我们推倒到第m+1行时,由于我们只计算了前m行的前k个最小值,那我们是不是有必要多计算一些来推导出第m+1行的前k个最小值呢, 答案是不必要的,我们可以通过以下数学公式严格证明:
设DP[x]是前m行通过计算得出的第x(x>k)小的和,如果上述的假设成立,那么我们可以列出不等式:
  DP[x] + A[y] < DP[m] + A[n] (1) (DP[m]+A[n]表示只通过DP[1,2...k]计算出的前m+1行第k小的和)
上述不等式的含义是指在第m+1行存在一个数A[y],使得DP[x]+A[y]是前m+1行中前k小的结果。
同时,我们注意到: x>k ==> DP[x] > DP[k] (2)
而且: A[y] >= A[1] (3)
由上面三个不等式(1),(2),(3)我们可以得到:
      DP[k]+A[1] <= DP[x]+A[y] < DP[m]+A[n]
也就是 DP[k]+A[1] < DP[m]+A[n]
之前我们说过DP[m] + A[n] 是前m行第k大的和,然而:比DP[k]+A[1]小的数已经有
(DP[1]+A[1]),(DP[2]+A[1])...(DP[k-1]+A[1])共计k-1个,
所以DP[k]+A[1]是第k个最小的和,与假设的DP[m]+A[n]是第k个最小的和相矛盾,所以假设不成立。
得证。 通过以上的证明我们可以得出结论要计算第m+1行的前k个最小和是只需要计算出前m行的前k个最小的和即可。
这时,我们的目标就转化为了计算一个2*k的数组,在第一行取一个数,在第二行取一个数,得到k^2个和,求他们当中的最小的k个和。 为了计算它,我们把这n^2个数组织成如下n个有序表:
表1: A1+B1 <= A1+B2<=A1+B3<=......
表2: A2+B1 <= A2+B2<=A2+B3<=......
.
表n: An+B1 <= An+B2<=An+B3<=...... 这时我们用一个二元组(sum, b)来保存以上的每一个元素,其中sum=A[a] + B[b].为什么不保存A的下标a呢?因为我们用不到a的值。如果我们需要在表(sum, b)中赵到下一个元素(sum', b+1),只要计算sum' = s - B[b] + B[b+1],不需要知道a是多少。
 struct Item {
int sum, b; //s = A[a] + B[b]
Item(int _s, int _b)
{
sum = _s;
b = _b;
}
bool operator < (const Item& rhs) const {
return sum > rhs.sum;
}
};

至于如何合并,见代码:(其中merge的功能是将a和b数组合并到一个数组a中,最后的结果保存在a中)

 #include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FOPENIN(IN) freopen(IN, "r", stdin)
#define FOPENOUT(OUT) freopen(OUT, "w", stdout) template<class T> T CMP_MIN(T a, T b) { return a < b; }
template<class T> T CMP_MAX(T a, T b) { return a > b; }
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } //typedef __int64 LL;
typedef long long LL;
const int MAXN = ;
const int MAXM = ;
const double eps = 1e-; struct NODE
{
int s, b;
NODE(){}
NODE(int _s,int _b)
{
s = _s;
b = _b;
}
bool operator < (const NODE& B)const{
return s > B.s;
}
};
int k, a[MAXN], b[MAXN]; void mergeArray()
{
priority_queue<NODE>q;
for(int i = ; i < k; i++)
{
q.push(NODE(a[i]+b[], ));
}
for(int i=;i<k;i++)
{
NODE top = q.top(); q.pop();
a[i] = top.s;
int id = top.b;
if(id+ < k) q.push(NODE(top.s+b[id+]-b[id], id+));
}
} int main()
{
// FOPENIN("in.txt");
// FOPENOUT("out.txt");
while(~scanf("%d", &k))
{
mem0(a);
for(int i=;i<k;i++) scanf("%d", &a[i]);
for(int i=;i<k;i++)
{
for(int j=;j<k;j++) scanf("%d", &b[j]);
sort(b,b+k);
mergeArray();
}
for(int i=;i<k;i++)
{
printf("%d%c", a[i],i==k-?'\n':' ');
}
}
return ;
}

												

UVa11997K Smallest Sums(优先队列)的更多相关文章

  1. 11997 - K Smallest Sums(优先队列)

    11997 - K Smallest Sums You’re given k arrays, each array has k integers. There are kk ways to pick ...

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

    UVA - 11997 id=18702" target="_blank" style="color:blue; text-decoration:none&qu ...

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

    题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...

  4. UVa 11997 K Smallest Sums - 优先队列

    题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和. 考虑将前i个数组合并,保留前k个和.然后考虑将第(i + 1)个数组和它合并,保留前 ...

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

    vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一 ...

  6. uva_11997,K Smallest Sums优先队列

    #include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...

  7. 373. Find K Pairs with Smallest Sums (java,优先队列)

    题目: You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Def ...

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

    UVa11997 K Smallest Sums  题目: K Smallest Sums You're given k arrays, each array has k integers. Ther ...

  9. [LeetCode] Find K Pairs with Smallest Sums 找和最小的K对数字

    You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...

随机推荐

  1. hdu 4622 Reincarnation trie树+树状数组/dp

    题意:给你一个字符串和m个询问,问你l,r这个区间内出现过多少字串. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 网上也有用后缀数组搞得. 思路 ...

  2. You must SET PASSWORD before executing this statement解决

    [转载] MySql5.6操作时报错:You must SET PASSWORD before executing this statement解决 转载: http://blog.csdn.net/ ...

  3. jsp 三大指令和动作标签

    jsp三大指令 一个jsp页面中可以有0-N个指令 1.page--->最复杂:<%@page language="" ...%> *pageEncoding和c ...

  4. (转)hadoop基本操作命令

    http://www.cnblogs.com/gpcuster/archive/2010/06/04/1751538.html 在这篇文章中,我们默认认为Hadoop环境已经由运维人员配置好直接可以使 ...

  5. Windows 8 电话激活密钥。(更新至 2013-07-21)

    MAK密钥,可用于电话激活专业版&企业版,2013.7.21 更新,共22枚: slmgr.vbs -ipk MQJNQ-G2TKM-YJP7W-CCXVY-VQR92slmgr.vbs -i ...

  6. IE6对CSS支持Bug收集

    1.IE6双外边距 在IE6下,如果对元素设置了浮动,同时又设置了margin-left或者margin-right,margin值会加倍. 例如,设置margin-left:10px在IE6下会显示 ...

  7. PHP校验ISBN码的函数

    国际标准书号(International Standard Book Number,ISBN:拟发音is-ben),是国际通用的图书或独立的出版物(除定期出版的期刊)代码.出版社可以通过国际标准书号清 ...

  8. ASP.NET静态页生成

    由于业务需要,得把页面按照模板页生成静态页面,所以自己就琢磨了下,写些思路,以备日后需要的时候用. 静态页生成用到最多的就是匹配跟替换了,首先得读取模板页的html内容,然后进行你自己定义的标签匹配, ...

  9. [Everyday Mathematics]20150221

    设 $y_n=x_n^2$ 如下归纳定义: $$\bex x_1=\sqrt{5},\quad x_{n+1}=x_n^2-2\ (n=1,2,\cdots). \eex$$ 试求 $\dps{\vl ...

  10. [Everyday Mathematics]20150220

    试求 $$\bex \sum_{k=0}^\infty\frac{1}{(4k+1)(4k+2)(4k+3)(4k+4)}. \eex$$