题目描述

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

解析

写这题完全自闭。

根本没联想起远古时期做的 P1631 序列合并 ,这题几乎是我刚入门做的了,代码还是仿的。

真的想了很久,怀疑自己智商.jpg。


首先如果做了 P1631 序列合并 而且还记得,那么这道题其实很好做。实际上就是把求两行的前\(k\)小和改成了求\(n\)行的前\(k\)小和。

两行的情况:设单调递增数列\(a,b\),其存在最小值\(a_1+b_1\),次小值为\(min(a_2+b_1,a_1+b_2)\)。

推广到一般,对于第\(k\)小值\(a_n+b_m\),我们有第\(k+1\)小值\(min(a_n+b_{m+1},a_{n+1}+b_m)\)。

因此有算法,我们将\(a_1+b_1\)加入优先队列,不断扩展,每次可扩展出两个可行解,执行\(k\)次,所以显然也有最终答案下标一定不会超过\(k\)。

\(n\)行的情况,我们在行与行间进行迭代,应用与两行情况类似的算法。

换句话说,对于递增的行\(x,y,z\),该算法就是先求\(x,y\)的前\(k\)小和,这些和组成新的数列,再跟\(z\)执行该算法,可以求出\(x,y,z\)三行的前\(k\)小和。

简单证明:

设\(x,y\)的前\(k\)小和构成的数列为\(x'\),\(sum(i,j)\)表示从第\(i,j\)行分别任意取一个元素相加得到的新数列。如果\(z\)中有一元素\(q\),其与一元素\(p\in sum(x,y)\),且\(p \notin x'\)相加构成\(sum(x',z)\)的第\(k'\)小值,且\(k'<k\)。那么一定有一元素\(p' \in x'\)与\(q\)构成更优的第\(k'\)小值,故这样的\(p\)不存在。即\(sum(x',z)=sum(x,y,z)\)。也就是说这个迭代是没有问题的。

参考代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 801
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node{
int val,ap,bp;
bool operator<(const node &a)const{
return a.val<val;
}
node(){}
node(int _v,int _a,int _b){val=_v,ap=_a,bp=_b;}
};
priority_queue<node> q;
int a[N],b[N],n,m,k,t[N];
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=m;++i) a[i]=read();
sort(a+1,a+m+1);
for(int i=2;i<=n;++i){
for(int j=1;j<=m;++j) b[j]=read();
sort(b+1,b+m+1);
while(q.size()) q.pop();//换成开个新的优先队列或许更快?
for(int j=1;j<=k;++j) q.push(node(a[j]+b[1],j,1));//小优化
for(int j=1;j<=k;++j){
node x=q.top();q.pop();
t[j]=x.val;
if(x.bp<m) q.push(node(a[x.ap]+b[x.bp+1],x.ap,x.bp+1));
}
memcpy(a,t,sizeof(a));//迭代
}
for(int i=1;i<=k;++i) printf("%d ",a[i]);
return 0;
}

P1392 取数[堆]的更多相关文章

  1. 洛谷P1392 取数 [堆]

    题目传送门 取数 题目描述 在一个n行m列的数阵中,你须在每一行取一个数(共n个数),并将它们相加得到一个和.对于给定的数阵,请你输出和前k小的取数方法. 输入输出格式 输入格式: 第一行,三个数n, ...

  2. P1392 取数

    P1392 取数 题目描述 在一个n行m列的数阵中,你须在每一行取一个数(共n个数),并将它们相加得到一个和.对于给定的数阵,请你输出和前k小的取数方法. 说明 对于20%的数据,n≤8 对于100% ...

  3. 2021.11.04 P1392 取数(多路归并)

    2021.11.04 P1392 取数(多路归并) P1392 取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 在一个n行m列的数阵中,你须在每一行取一个数(共n个数) ...

  4. 洛谷 P1392 取数

    题面 在做这道题前,先要会他的弱化版(实际一模一样,只是愚蠢的洛谷评测级别差了一档(睿智如姬无夜)) ----------------------------------弱化版------------ ...

  5. [洛谷P1392] 取数

    无法用复杂状态进行转移时改变计算方式:巧妙的整体考虑:压缩空间优化时间 传送门:$>here<$ 题意 给出一个n*m矩阵,从每一行选一个数加起来,可以得到一个和.易知总共会有$n^n$个 ...

  6. 【 HDU 2177 】取(2堆)石子游戏 (威佐夫博弈)

    BUPT2017 wintertraining(15) #5C hdu2177 题意 两个人轮流取石子,可以取一堆的任意非负整数个或两堆取相同个,先取完的输. 给定若干组数据:a,b表示两堆的石子数量 ...

  7. HDU2177取(2堆)石子游戏---(威佐夫博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=2177 取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    M ...

  8. P2774 方格取数问题 网络最大流 割

    P2774 方格取数问题:https://www.luogu.org/problemnew/show/P2774 题意: 给定一个矩阵,取出不相邻的数字,使得数字的和最大. 思路: 可以把方格分成两个 ...

  9. 洛谷P1288 取数游戏II[博弈论]

    题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...

随机推荐

  1. (CSDN迁移) 输入一个链表,从尾到头打印链表每个节点的值

    题目描述 输入一个链表,从尾到头打印链表每个节点的值. 思路1. 翻转链表,使用java自带的翻转函数或者从头到尾依次改变链表的节点指针 /** * public class ListNode { * ...

  2. 百练1724 ROADS

    总时间限制: 1000ms    内存限制: 65536kB 描述 N cities named with numbers 1 ... N are connected with one-way roa ...

  3. @Component和@Configuration作为配置类的差别

    https://blog.csdn.net/long476964/article/details/80626930 虽然Component注解也会当做配置类,但是并不会为其生成CGLIB代理Class ...

  4. 华为路由器+三层交换,路由器配置DHCP,交换机中继DHCP

    LSW14:undo terminal monitorsystem-viewsysname SW1vlan batch 10 20 30 40 66interface Ethernet0/0/1por ...

  5. 深度解析qml引擎---(1)Qml文件加载

                                                                        "美的事物是永恒的喜悦" --- 济慈    ...

  6. LeetCode 92. 反转链表 II(Reverse Linked List II)

    92. 反转链表 II 92. Reverse Linked List II 题目描述 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. LeetC ...

  7. 【C++面试】关于虚函数的常见问题

    1.虚函数的代价 1)带有虚函数的每个类会产生一个虚函数表,用来存储虚成员函数的指针 2)带有虚函数的每个类都会有一个指向虚函数表的指针 3)不再是内敛函数,因为内敛函数可以在编译阶段进行替代,而虚函 ...

  8. linux net通信 基于密钥

    配置SSHD服务 SSH(Secure Shell)是一种能够以安全的方式提供远程登录的协议,也是目前远程管理 Linux 系统的首选方式.在此之前,一般使用 FTP 或 Telnet 来进行远程登录 ...

  9. Codeforces 1207 G. Indie Album

    Codeforces 1207 G. Indie Album 解题思路 离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = l ...

  10. [高清·非影印] 深度学习入门:基于Python的理论与实现 + 源代码

    ------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...