您的位置:首页 > 产品设计 > UI/UE

POJ 2442 Sequence 堆的思想的应用 STL 堆学习

2016-02-23 13:15 411 查看
点击打开链接

下面再介绍STL中与堆相关的4个函数——建立堆make_heap(),在堆中添加数据push_heap(),在堆中删除数据pop_heap()和堆排序sort_heap():
头文件 #include <algorithm>
下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。
建立堆
make_heap(_First, _Last, _Comp)
默认是建立最大堆的。对int类型,可以在第三个参数传入greater<int>()得到最小堆。

在堆中添加数据 ///只对最后一个元素进行堆 排序 所以加数据要在最后一位加
push_heap (_First, _Last)
要先在容器中加入数据,再调用push_heap ()

在堆中删除数据 /// 栈顶元素与最后的元素进行了交换(跑到最后去了)
pop_heap(_First, _Last)
要先调用pop_heap()再在容器中删除数据

堆排序
sort_heap(_First, _Last)

排序之后就不再是一个合法的heap了

#include <cstdio>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
void PrintfVectorInt(vector<int> &vet)
{
for (vector<int>::iterator pos = vet.begin(); pos != vet.end(); pos++)
printf("%d ", *pos);
putchar('\n');
}
int main()
{
const int MAXN = 20;
int a[MAXN];
int i;
for (i = 0; i < MAXN; ++i)
a[i] = rand() % (MAXN * 2);

//动态申请vector 并对vector建堆
vector<int> *pvet = new vector<int>(40);
pvet->assign(a, a + MAXN);

//建堆
make_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);

//加入新数据 先在容器中加入,再调用push_heap()
pvet->push_back(25);
push_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);

//删除数据  要先调用pop_heap(),再在容器中删除
pop_heap(pvet->begin(), pvet->end());
pvet->pop_back();
pop_heap(pvet->begin(), pvet->end());
pvet->pop_back();
PrintfVectorInt(*pvet);

//堆排序
sort_heap(pvet->begin(), pvet->end());
PrintfVectorInt(*pvet);

delete pvet;
return 0;
}


题意:给你m个数字集合 每个数字集合中有n个数字

从m个串中挑选一个数字加起来,共有n^m 中相加的方法

求按非降序的顺序输出前n个最小的和

思路:

利用堆的思想将求从m 个数字集合中挑选m 个数字相加

这个m个数相加的过程一步一步的进行

让现有的和与堆中的和进行比较,判断是否更改堆顶;

{

先让堆中的元素随意加入第i个数字 (以加入第一个为例)

然后让现在的堆顶 与 加入其他数字进行比较,判断是否需要更改

}

步骤:

利用两个数组和一个堆进行做

1 a[]表示在添加第i个数字前 的前n个小的和

{即输入第i个串之前 的和}

2 b[]表示当前输的第i串中的数字

3 heap[]表示堆储存

4

[1]

先将第一组串作为堆的基础(a[]有序的)

[2]

输入下一组串b (排序)

然后让堆中的每个数字都加上b[1];

接着让堆顶(为堆中最大数字)与 a[1...n]+b[2...n],进行比较

{

大于

就更新堆顶数字

小于

退出 (有优化的过程(因为提前对a[],b[]都排序了);

}

重复[2] 直到输入了m行

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int heap[3000],a[3000],b[3000];
void adjust(int ind,int len)
{
int lch=ind<<1;
int rch=ind<<1|1;
int Max=ind;
if(ind<=len/2)
{
if(lch<=len&&heap[lch]>heap[Max])
Max=lch;
if(rch<=len&&heap[rch]>heap[Max])
Max=rch;
if(Max!=ind)
{
swap(heap[Max],heap[ind]);
adjust(Max,len);
}
}
}
int main()
{
int T;
int n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
heap[i]=a[i];
for(int i=n/2;i>=1;i--)
adjust(i,n);                ///一个数的时候的堆的创建
///为了使元素满足根大于左右孩子

for(int i=2;i<=m;i++)
{
sort(a+1,a+n+1);        ///排序 优化if(heap[1]>a[k]+b[j])
for(int j=1;j<=n;j++)
scanf("%d",&b[j]);
sort(b+1,b+n+1);
for(int j=1;j<=n;j++)
heap[j]+=b[1];         ///建立拥有i个数字相加和的堆
for(int j=2;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(heap[1]>a[k]+b[j])     ///堆顶与其他相加和进行比较
{
heap[1]=a[k]+b[j];
adjust(1,n);
}
else
break;
}
}
for(int j=1;j<=n;j++)    ///用a[]来存 拥有i个数字相加和的前n个最小和
a[j]=heap[j];
}
sort(heap+1,heap+1+n);
for(int i=1;i<n;i++)
printf("%d ",heap[i]);
printf("%d\n",heap
);
}
return 0;
}
STL 堆
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int heap[3000],a[3000],b[3000];
int main()
{
int n,m,T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++)
{ scanf("%d",&a[i]);
heap[i]=a[i];
}
make_heap(heap,heap+n);
for(int i=1;i<m;i++)
{
sort(a,a+n);
for(int j=0;j<n;j++)
scanf("%d",&b[j]);
sort(b,b+n);
for(int j=0;j<n;j++)
heap[j]+=b[0];

for(int j=1;j<n;j++)
{
for(int k=0;k<n;k++)
{
if(heap[0]>a[k]+b[j])
{
pop_heap(heap,heap+n);   ///堆顶不会消失,移动到了最后
heap[n-1]=a[k]+b[j];
push_heap(heap,heap+n);   ///只对最后一个元素进行重新堆排序
}
else
break;
}
}
for(int j=0;j<n;j++)
a[j]=heap[j];
}
sort(heap,heap+n);
for(int i=0;i<n-1;i++)
printf("%d ",heap[i]);
printf("%d\n",heap[n-1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: