本文出自:http://blog.csdn.net/svitter
题意分析:
Given m sequences, each contains n non-negative integer. Now we may select one number from each sequence to form a sequence with m integers. It‘s clear
that we may get n ^ m this kind of sequences. Then we can calculate the sum of numbers in each sequence, and get n ^ m values. What we need is the smallest n sums. Could you help us?
给你m个序列,每个包含n个非负的整数。现在我们需要从每一个序列中选择一个整数。我们可以很简单的得出一个一共有n^m个组合。我们可以计算出每个序列的加和,并且得到n^m组值。我们需要n组最小序列和。
输入输出分析:
The first line is an integer T, which shows the number of test cases, and then T test cases follow. The first line of each case contains two integers m,
n (0 < m <= 100, 0 < n <= 2000). The following m lines indicate the m sequence respectively. No integer in the sequence is greater than 10000.
给T组测试样例。第一行包括两个整数m,n分别代表m个序列, n个整数。没有整数大于10000(没有超过int)
算法数据结构分析:
利用动态规划思想,分阶段解决问题。
使用两个数组作为滚动数组,利用c= 1-c进行切换。
a代表前k-1个序列的最小序列和的分布,b代表前k个序列最小阶段序列和。读入新的序列进行计算。
新读入的序列不停的更新b的阶段最小序列和,方法:用每一项与a中的每一个元素求和,计算出的b如果小于b数组的最大值,弹出最大值,将新计算出值加入b
假设数据为:
3 3
1 2 3
1 2 3
3 2 1
可得
2 3 4
3 4 5
4 5 6
取2 3 3
2 3 3
3 2 1
可得
5 6 6
4 5 5
3 4 4
取3 4 4
由此可见每次都是取都是取最佳的组合。
使用堆数据结构来获得每次的最大值。堆的实现包含在algorithm中(大顶堆)
AC代码:
#include <iostream> #include <cstdio> #include <string.h> #include <queue> #include <algorithm> using namespace std; #define MAXN 2010 int m, n; int t; int a[2][MAXN]; int main() { int i, j, k; int c; int temp1, temp2; freopen("test/test2", "r", stdin); scanf("%d", &t); while(t--) { scanf("%d%d", &m, &n); for(i = 0; i < n; i++) scanf("%d", &a[0][i]); make_heap(a[0], a[0]+n); c = 0; for(i = 1; i < m; i++, c = 1-c) { scanf("%d", &temp1); for(k = 0; k < n; k++) a[1-c][k] = a[c][k] + temp1; for(k = 1; k < n; k++) { scanf("%d", &temp1); for(j = 0; j < n; j++) { temp2 = a[c][j] + temp1; if(temp2 < a[1-c][0]) { pop_heap(a[1-c], a[1-c]+n); a[1-c][n-1] = temp2; push_heap(a[1-c], a[1-c]+n); } } } } sort(a[c], a[c]+n); for(i = 0; i < n-1; i++) printf("%d ", a[c][i]); printf("%d\n", a[c][n-1]); } return 0; }
POJ2442——Squence(二叉堆+动态规划 | 滚动数组)