UVa11997K 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 题目大意:
给定一个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(优先队列)的更多相关文章
- 11997 - K Smallest Sums(优先队列)
11997 - K Smallest Sums You’re given k arrays, each array has k integers. There are kk ways to pick ...
- UVa 11997 K Smallest Sums 优先队列&&打有序表&&归并
UVA - 11997 id=18702" target="_blank" style="color:blue; text-decoration:none&qu ...
- uva 11997 K Smallest Sums 优先队列处理多路归并问题
题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...
- UVa 11997 K Smallest Sums - 优先队列
题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和. 考虑将前i个数组合并,保留前k个和.然后考虑将第(i + 1)个数组和它合并,保留前 ...
- UVA 11997 K Smallest Sums 优先队列 多路合并
vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一 ...
- uva_11997,K Smallest Sums优先队列
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
- 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 ...
- 【暑假】[实用数据结构]UVa11997 K Smallest Sums
UVa11997 K Smallest Sums 题目: K Smallest Sums You're given k arrays, each array has k integers. Ther ...
- [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 ...
随机推荐
- hibernate的oracle配置(转)
连接Oracle数据库的Hibernate配置文件连接Oracle的Hibernate配置文件有两种格式,一种是xml格式的,另一种是Java属性文件格式的.下面分别给出这两种格式配置文件的代码. 1 ...
- zipline tradingcalendar
zipline/utils/ tradingcalendar.py tradingcalendar_bmf.py 巴西商品期货交易所 tradingcalendar_lse.py 伦敦证券交易所 tr ...
- linux中备份mysql数据库的一个shell脚本
#!/bin/bash #FileName:select_into_bak.sh #Desc:Use select into outfile to backup db or tables #Creat ...
- fmri的图像数据在matlab中显示,利用imagesc工具进行显示,自带数据集-by 西南大学xulei教授
这里包含了这样一个数据集:slice_data.mat. 这个数据集中包含的mri数据是:64*64*25.共有25个slice.每个slice的分辨率是64*64. 程序非常简短: load sli ...
- php使用第三方登录
目前只做了微博和qq的,前面的去connect.qq.com,open.weibo.com注册的步骤省略 qq和weibo站点都有可以现在的php版本的api,qq的api相对高大上一些. <s ...
- hadoop完全分布式模式的安装和配置
本文是将三台电脑用路由器搭建本地局域网,系统为centos6.5,已经实验验证,搭建成功. 一.设置静态IP&修改主机名&关闭防火墙(all-root)(对三台电脑都需要进行操作) 0 ...
- 转:移动开发中一些bug及解决方案
网页开发要面对各种各样的浏览器,让人很头疼,而移动开发中,你不但要面对浏览器,还要面对各种版本的手机,iOS好一点,而安卓就五花八门了,你可能在开发中也被它们折磨过,或者正在被它们折磨,我在这里说几个 ...
- MySQL与Oracle 差异比较之四条件循环语句
循环语句 编号 类别 ORACLE MYSQL 注释 1 IF语句使用不同 IF iv_weekly_day = 'MON' THEN ii_weekly_day := 'MON';ELS ...
- K2 Blackpearl开发技术要点(Part2)
转:http://www.cnblogs.com/dannyli/archive/2012/09/14/2685282.html K2 Blackpearl开发技术要点(Part2)
- JSTL笔记(胖先生版)
今天系统的学习了一下jstl,来记录一下. 在学习jstl以前,先要引两个jar包,然后再加入标签: <%@ taglib prefix="c" uri="http ...