今天我们还是学了堆这个概念,不过题目的难度也有所提高,并不是模板题那么简单。下面上一道题目:
取数
题目描述
在一个n行m列的数阵中,你须在每一行取一个数(共n个数),并将它们相加得到一个和。对于给定的数阵,请你输出和前k小的取数方法。
输入输出格式
输入格式:
第一行,三个数n,m,k。
第2~n+1行,每行m个正整数
输出格式:
一行共k个数,代表在每一行取一个数前k小的加和
输入输出样例
说明
对于20%的数据,n≤8
对于100%的数据,n≤800,k≤m≤800
思路 (此题只讲思路,不给代码)
这题看起来并不是很难,毕竟第一个数还是很好求的嘛。。但是接下来就比较棘手了。
因为这题有n行,所以我们可以先做一个两行的(为方便计算,我把第一行记作a[],第二行记作b[]),得出来的值再形成一行,依次做两行,就可以把n行都做完了。
第一个最小的肯定是第一行的第一个数加上第二行的第一个数,于是把a[1]+b[1]入堆。
但是第二个最小的可以是a[1]+b[2],也可以是a[2]+b[1],怎么办呢?欸,我可以都入堆啊。于是可以得到,每次发现a[i]+b[j]是最小值时,我就可以将a[i+1]+b[j]和a[i]+b[j+1]入堆。
但是这样做还是有点问题,比如a[i-1]+b[j]和a[i]+b[j-1]都可以得到a[i]+b[j],将其入堆,那不就重复入堆了吗?
于是我就还需要一个标记,这样一来,我入堆的东西就可以是一个结构体了(没想到吧),一个存i,一个存j,一个存值,一个存标记,然后根据值的大小来执行四个操作,具体操作见我前面的随笔。
然后这个用结构体入堆的步骤,我可以给你一个简便的方法:
kpush((PP){a[i]+a[j],1,1,0});//前面的小括号里是结构体名,后面的大括号里填结构体的参数
这样就可以直接入堆。
最后还是推荐一个自己建堆的网站:自己建堆。