pku2442 Sequence
2010-06-03 19:16
274 查看
题意是 给出 m组数,
每组 n个数 然后从m组中 每组选出一个进行求和 ,然后取其中前n小的数输出
选择的总数自然是 n的m次方,暴力法自然是超时的。
一个简单的思路是,从第一组到第m组依次处理
首先第一组的n个数自然是最小的n个数, 然后这n个数和第二组的n个组进行组合,形成n×n个数,保留其前n个数,再处理第三组,依次类推直到第m组
为什么保留前n个数就可以了呢? 我们以第一组和第二组例所得的n×n个数为例,假设保留n+1个数,且这第n+1个数加上第三组的某个数x的和 在下一步中需要保留(即在下一步操作中属于前n小的数之一),然而前n个数中的任意一个数+x < 第n+1个数+x ,此时得出矛盾, 由此可知,每次处理后的n×n个数中只需保留前n个数即可
一开始为了方便 偷懒 开了一个n*n的数组,想用 sort排序后取前n个数,交上去超时了,于是改用堆了
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int heap[2010]; //堆
int a[2010];
int b[2010];
int len;
inline int pri()
{
return heap[1];
}
inline void init()
{
len=0;
}
inline int com(int a,int b)
{
return a>b?1:0;
}
//插入操作,先插到末尾,然后逐步和自己的父亲比较,向上移动
void insert(int x)
{
heap[++len]=x;
int i=len;
while (i>1&&x>heap[i>>1])
{
heap[i]=heap[i>>1];
i>>=1;
}
heap[i]=x;
}
//删除操作
void del()
{
int i,j;
j=1;
i=2;
while (i<len)
{
i+=com(heap[i+1],heap[i]);
if (com(heap[len],heap[i])) break;
heap[j]=heap[i];
j=i;
i<<=1;
}
heap[j]=heap[len--];
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int m,n;
scanf("%d%d",&m,&n);
int i,j,k;
for (i=1;i<=n;++i)
{
scanf("%d",a+i);
insert(a[i]);
}
for (i=1;i<m;++i)
{
for (j=1;j<=n;++j)
scanf("%d",b+j);
for (k=n;k>=1;--k)
{
a[k]=pri();
del();
}
init();
int s;
for (k=1;k<=n;++k)
{
for (s=1;s<=n;++s)
{
if (len<n) insert(a[k]+b[s]); //如果不到n个数,则直接插入
else
{
if (pri()>a[k]+b[s])
{
del(); //已经有n个数了,这和这n个数中最大的数,即堆中第一个元素比较,如果比它小,则插入
insert(a[k]+b[s]);
}
}
}
}
}
for (i=n;i>=1;--i)
{
a[i]=pri();
del();
}
printf("%d",a[1]);
for (i=2;i<=n;++i)
printf(" %d",a[i]);
printf("/n");
}
return 0;
}
每组 n个数 然后从m组中 每组选出一个进行求和 ,然后取其中前n小的数输出
选择的总数自然是 n的m次方,暴力法自然是超时的。
一个简单的思路是,从第一组到第m组依次处理
首先第一组的n个数自然是最小的n个数, 然后这n个数和第二组的n个组进行组合,形成n×n个数,保留其前n个数,再处理第三组,依次类推直到第m组
为什么保留前n个数就可以了呢? 我们以第一组和第二组例所得的n×n个数为例,假设保留n+1个数,且这第n+1个数加上第三组的某个数x的和 在下一步中需要保留(即在下一步操作中属于前n小的数之一),然而前n个数中的任意一个数+x < 第n+1个数+x ,此时得出矛盾, 由此可知,每次处理后的n×n个数中只需保留前n个数即可
一开始为了方便 偷懒 开了一个n*n的数组,想用 sort排序后取前n个数,交上去超时了,于是改用堆了
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int heap[2010]; //堆
int a[2010];
int b[2010];
int len;
inline int pri()
{
return heap[1];
}
inline void init()
{
len=0;
}
inline int com(int a,int b)
{
return a>b?1:0;
}
//插入操作,先插到末尾,然后逐步和自己的父亲比较,向上移动
void insert(int x)
{
heap[++len]=x;
int i=len;
while (i>1&&x>heap[i>>1])
{
heap[i]=heap[i>>1];
i>>=1;
}
heap[i]=x;
}
//删除操作
void del()
{
int i,j;
j=1;
i=2;
while (i<len)
{
i+=com(heap[i+1],heap[i]);
if (com(heap[len],heap[i])) break;
heap[j]=heap[i];
j=i;
i<<=1;
}
heap[j]=heap[len--];
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int m,n;
scanf("%d%d",&m,&n);
int i,j,k;
for (i=1;i<=n;++i)
{
scanf("%d",a+i);
insert(a[i]);
}
for (i=1;i<m;++i)
{
for (j=1;j<=n;++j)
scanf("%d",b+j);
for (k=n;k>=1;--k)
{
a[k]=pri();
del();
}
init();
int s;
for (k=1;k<=n;++k)
{
for (s=1;s<=n;++s)
{
if (len<n) insert(a[k]+b[s]); //如果不到n个数,则直接插入
else
{
if (pri()>a[k]+b[s])
{
del(); //已经有n个数了,这和这n个数中最大的数,即堆中第一个元素比较,如果比它小,则插入
insert(a[k]+b[s]);
}
}
}
}
}
for (i=n;i>=1;--i)
{
a[i]=pri();
del();
}
printf("%d",a[1]);
for (i=2;i<=n;++i)
printf(" %d",a[i]);
printf("/n");
}
return 0;
}
相关文章推荐
- pku 2442 Sequence stl堆的应用
- POJ 2442 Sequence(优先队列)
- POJ 2442 Sequence(堆的应用)
- poj2442 Sequence----堆复习
- poj_2442_Sequence_堆
- poj 2442 Sequence 堆
- POJ - 2442 Sequence(优先队列/堆)
- poj 2442 Sequence(堆)
- POJ-2442 Sequence
- POJ 2442 Sequence 堆
- 【POJ 2442】Sequence
- poj-2442-Sequence-优先队列||堆
- POJ 2442 Sequence
- POJ-2442 Sequence(优先队列)
- POJ 2442-Sequence(优先队列-m组n个数每组取一个求n个最小值)
- POJ 2442 Sequence (堆)
- pku2081----Recaman's Sequence(按所给的递推公式来做就行)