首页 > 代码库 > POJ2442——Squence(二叉堆+动态规划 | 滚动数组)

POJ2442——Squence(二叉堆+动态规划 | 滚动数组)

本文出自: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;
}