超链接:Sequence
Description 给定m个数字序列,每个序列包含n个非负整数。我们从每一个序列中选取一个数字组成一个新的序列,显然一共可以构造出n^m个新序列。接下来我们对每一个新的序列中的数字进行求和,一共会得到n^m个和,请找出最小的n个和
每个测试用例输入的第一行是两个正整数m(0 < m <= 100)和n(0 < n <= 2000),然后有m行,每行有n个数,数字之间用空格分开,表示这m个序列
序列中的数字不会大于10000
1 2 3 1 2 3 2 2 3
3 3 4
分析:维护一个长度为n的优先队列,每次输入后都对前n个最小和进行更新,m-1次迭代后得到最终的前n个最小和。
起初想了好久都不知道怎么用二叉树写,最后参考了别人的程序用了优先队列,虽然没有练习到二叉树的底层操作,但是练了下优先队列的应用也是可以的。
这里比较尴尬的情况是,看了别人的程序,然后根据别人的思路把题做出来后,是标明原创还是标明转载呢?貌似都感觉怪怪的。或许这就是某些同学不用csdn博客的原因吧。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 2005;
int t,m,n,a[maxn],b[maxn];
priority_queue<int> q;//利用a维护前n个最小和
int main()
{
scanf("%d",&t);
while(t--) {
scanf("%d%d",&m,&n);
for (int i = 0; i < n; ++i) scanf("%d",&a[i]);sort(a,a+n); //a存储前n个最小和
m--;
while(m--) {
for (int i = 0; i < n; ++i) scanf("%d",&b[i]);sort(b,b+n);
for (int i = 0; i < n; i++) q.push(a[i]+b[0]); //生成长度为n的优先队列
for (int i = 1; i < n; ++i) { //计算剩余的组合,并更新队列
int j;
for (j = 0; j < n; ++j)
if(b[i]+a[j]<q.top()) q.pop(),q.push(b[i]+a[j]);//a剪枝
else break;
if(j == 0) break;//b剪枝,b[i]+a[0]都不行,那b[i+1]+a[0]或b[i]+a[1]也不行
}
for (int i = n-1; i >= 0; i--) a[i] = q.top(),q.pop(); //为下次更新作准备
}
for (int i = 0; i < n; i++) printf("%d%c",a[i],i == n-1?'\n':' ');
}
return 0;
}
参考:http://blog.youkuaiyun.com/m0_37975647/article/details/77898419
ps:用dp貌似也行,懒得看了。现在重点是二叉树。