動態規划--最長上升子序列(Longest increasing subsequence)


  前面寫了最長公共子序列的問題。然后再加上自身對動態規划的理解,真到簡單的DP問題很快就解決了。其實只要理解了動態規划的本質,那么再有針對性的去做這方的題目,思路很快就會有了。不錯不錯~加油

  題目描述:POJ2533

  給出一個數列,找出這個數列中最長上升子序列中所包含的個數。

  解題思路:

  DP問題解題的一般方法就是自下而上,即先求解小的問題,然后再根據小的問題來解決大的問題,最后得到解。但是這里還要滿足的條件是最優子結構,即最優解包含着其子問題的最優解。

  那么我們首先用arr[]數組(從0下標開始)存儲要求的數列,用longest_num[i]數組來記錄以i為結尾的子序列里面包含的最長上升子序列的數字個數。然后用循環控制,從下標為1開始求longest_num,並且記錄找到的最大值,即可得到解。在我的程序里面,我還加了一個功能就是把最長上升子序列打印出來,如果存在有多個的話,那么就只打印最后一個。

  最后根據下面的DP方程就可以進行求解了:

  longest_num[i] = max{longest_num[j] + 1,longest_num[i]}     其中j < i && arr[j] < arr[i]

  程序:

  

#include <stdio.h>

#define MAX_N 1001
    
int arr[MAX_N];
int longest_num[MAX_N];
int bt[MAX_N];
int max_point = 0;

int LIS(int n)
{
 
    int max = 1;  //最長上升子序列的個數
    int i,j;
    
    for (i = 0; i < n; i++)   //i下標之前(包括i)的最長上升子序列的個數
    {
        longest_num[i] = 1; 
    }

    for (i = 0; i < n; i++)   //用於回溯
    {
        bt[i] = -1; 
    }


    for (i = 1; i < n; i++)
    {
        for (j = 0; j < i; j++)
        {
            if (arr[i] > arr[j] && longest_num[i] < longest_num[j] + 1)
            {
                longest_num[i] = longest_num[j] + 1;
                if (longest_num[i] >= max)
                {
                    max = longest_num[i];
                    max_point = i;
                    bt[i] = j;
                }
            }
        }
    }

    return max; 
}

void backtrack(int point)
{
    if (-1 == bt[point]) 
    {
        printf("%d ",arr[point]);
        return;
    }
    else
    {
        backtrack(bt[point]);
        printf("%d ",arr[point]);
    }
}

int main()
{
    int n,i,ret;
    FILE *fp;

    fp = fopen("in.txt","r");
    if (fp == NULL)
    {
        printf("fopen error!\n");
        return -1;
    }

    fscanf(fp,"%d",&n);
    for (i = 0; i < n; i++)
    {
        fscanf(fp,"%d",&arr[i]);
    }

    ret = LIS(n);
    printf("%d\n",ret);
    
    backtrack(max_point);
    printf("\n");

    return 0;
}

2013/8/16 16:21

   測試數據:

  7
  1 7 3 5 9 4 8

  測試結果:  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM