3

我有这个用于查找最长递增子序列(LIS)的代码,但是当我测试我的代码时,我没有得到最大和,例如:

如果我输入 20 1 4 3 10 答案是 1 3 10,但我需要 1 4 10 这是我的 C 代码:

#include <stdio.h>
#include <stdlib.h>

#define INT_INF 1000

int search_replace(int *lis, int left, int right, int key) {
    int mid;

    for (mid = (left+right)/2; left <= right; mid = (left+right)/2) {
            if (lis[mid] > key) {
                    right = mid - 1;
            } else if (lis[mid] == key) {
                    return mid;
            } else if (mid+1 <= right && lis[mid+1] >= key) {
                    lis[mid+1] = key;
                    return mid+1;
            } else {
                    left = mid + 1;
            }
    }
    if (mid == left) {
            lis[mid] = key;
            return mid;
    }
    lis[mid+1] = key;
    return mid+1;
}

int main() {
    int size, i;

    scanf(" %d", &size);

    int A[size];

    for(i = 0; i < size; i++){
        scanf(" %d", &A[i]);
    }

    int tmp, lis_length = -1;
    int *answer;
    int LIS[size];
    int index[size];

    LIS[0] = A[0];
    for (i = 1; i < size; ++i) {
            LIS[i] = INT_INF;
    }

    for (i = 1; i < size; ++i) {
            index[i] = search_replace(LIS, 0, i, A[i]);
            if (lis_length < index[i]) {
                    lis_length = index[i];
            }
    }

    answer = (int*) malloc((lis_length+1) * sizeof(int));
    for (i = size-1, tmp = lis_length; i >= 0; --i) {
            if (index[i] == tmp) {
                    answer[tmp] = A[i];
                    --tmp;
            }
    }

    printf("LIS: ");
    for (i = 0; i < lis_length+1; ++i) {
            printf("%d ", answer[i]);
    }
    printf("\n");

    return 0;
}

第一个输入是数组中元素的数量。

我已经尝试过这篇文章:Find the Longest increasing Subsequence with the Maximum Sum和其他一些但没有成功。

4

1 回答 1

0

我已经分析了你的代码并发现了你的问题:你没有找到最大总和的lis的代码,你只有简单的lis搜索。我已经添加了缺失的部分,现在代码可以正常工作了。另外,我编写了自己的解决方案,使用了另一种lis搜索算法,没有使用二分搜索。

注意:(left+right)/2寻找中间值的方法,有一个问题 -几乎所有的二分搜索和合并排序都是 Broken

你的代码加上我的补充:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define INT_INF 1000

int search_replace(int *lis, int left, int right, int key) {
    int mid;
    for (mid = (left+right)/2; left <= right; mid = (left+right)/2) {
        if (lis[mid] > key) {
            right = mid - 1;
        } else if (lis[mid] == key) {
            return mid;
        } else if (mid+1 <= right && lis[mid+1] >= key) {
            lis[mid+1] = key;
            return mid+1;
        } else {
            left = mid + 1;
        }
    }
    if (mid == left) {
        lis[mid] = key;
        return mid;
    }
    lis[mid+1] = key;
    return mid+1;
}

int main() {
    int size, i;

    scanf(" %d", &size);

    int A[size];

    for(i = 0; i < size; i++){
        scanf(" %d", &A[i]);
    }

    int tmp, lis_length = -1;
    int LIS[size];
    int index[size];

    LIS[0] = A[0];
    for (i = 1; i < size; ++i) {
        LIS[i] = INT_INF;
    }

    for (i = 1; i < size; ++i) {
        index[i] = search_replace(LIS, 0, i, A[i]);
        if (lis_length < index[i]) {
            lis_length = index[i];
        }
    }
    
    //////// my addition starts
    int max, j;
    // INT_MAX - the maximum number of the integer type.
    // The "limits.h" header is needed for this.
    int prev = INT_MAX;
    int answer[lis_length + 1];
    // Iterating through the "index" values.
    // On the each iteration, the checking all sequences 
    // with the same length
    // and determining the max value among them.
    // Starts from the lis_length and goes to the zero.
    for(i = lis_length; i >= 0; i--) {
        max = INT_MIN;
        for(j = 0; j < size; j++) {
            if(    index[j] == i 
                && A[j] > max 
                && A[j] < prev) {
                    
                max = A[j];
            }
        }
        answer[i] = max;
        prev = max;
    }
    //////// my addition ends

    printf("LIS: ");
    for (i = 0; i < lis_length+1; ++i) {
        printf("%d ", answer[i]);
    }
    printf("\n");

    return 0;
}

这是我的评论解决方案。

我用这个算法来确定lis。如果需要,请提出问题。

#include <stdio.h>
#include <limits.h>

int main() {
    int size = 0;
    int arr_nums[100];
    // Initialize all array values to the one. This is the GCC feature.
    int seq_lens[100] = {[0 ... 99] = 1};

    // Gets input numbers.
    while(scanf("%d", arr_nums + size) == 1) {
        size++;
    }
    // Fill the seq_lens array with sequences's lenghts.
    int i, j;
    int lis_num = 1;
    for(i = 1; i < size; i++) {
        for(j = 0; j <= i; j++) {
            if(     arr_nums[i] > arr_nums[j] 
                && (seq_lens[j] + 1 > seq_lens[i])) {

                    seq_lens[i] = seq_lens[j] + 1;
            }
        }
        // Finding the LIS number (the maximum sequence length).
        // If the previous LIS number is lesser then current, 
        // change it to the current.
        if(lis_num < seq_lens[i])
            lis_num = seq_lens[i];
    }

    // Finding the LIS with the maximum sum
    int max;
    // INT_MAX - the maximum number of the integer type.
    // The "limits.h" header is needed for this.
    int prev = INT_MAX;
    int lis_arr[lis_num];
    // Iterating through the seq_lens values.
    // On the each iteration, the checking all sequences with the same length
    // and determining the max value among them.
    // Starts from the LIS (the longest sequence number) 
    // and goes to the one (the minimum possible sequence number).
    for(i = lis_num; i > 0; i--) {
        max = INT_MIN;
        for(j = 0; j < size; j++) {
            if(    seq_lens[j] == i 
                && arr_nums[j] > max 
                && arr_nums[j] < prev) {
                    
                max = arr_nums[j];
            }
        }
        lis_arr[i - 1] = max;
        prev = max;
    }

    printf("The longest increasing sequence number is:\n%d\n", lis_num);

    puts("\nThe longest increasing sequence with the max sum is: ");
    for(i = 0; i < lis_num; i++) {
        printf("%d ", lis_arr[i]);
    }
    puts("");

    return 0;
}

输入

0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15

输出

The longest increasing sequence number is:
6

The longest increasing sequence with the max sum is: 
0 4 6 9 13 15 
于 2017-11-13T21:36:57.943 回答