动态规划 dp02 最长非降子序列问题 c代码
先看下題目:
給定一個由n個正整數組成的序列,從該序列中刪除若干個整數,使剩下的整數組成非降子序列,求 最長的非降子序列。 例如,由12個正整數組成的序列為:48,16,45,47,52,46,36,28,46,69,14,42 請在序列中刪除若干項,使剩下的項為非降(即后面的項不小于前面的項)序列,剩下的非降序列 最多為多少項?這道題第一次做是會做的,刷了兩天動態規劃類題目,第二次做的時候,不會了 ( ̄_, ̄ ),難道dp類題目刷的不夠多?
我們知道,動態規劃類題目通常分為三個步驟求解:
1. 分階段。
2. 狀態遷移方程。
3. 求取最優解。
第一次做思考了一下就想到方案了,第二次做的時候沒思考就想著套動態規劃的解題過程,結果把自己套沒了...... 看來解決問題不能套公式,靈活處理最重要。
對于這套題目,設數組a[n], 假設M[i]表示從i~n的最長非降數列長度,邊界情況是m[n] = 1;從后往前遍歷,求m[i],對于任意一個j, i < j < n;
如果a[i] <= a[j],則m[i] = m[j] + 1; 遍歷[i+1, n],找到最大的m[i]即可。
狀態遷移方程得到了,求取最優解序列的時候,遍歷m[i],找到最大值i,順著i打印即可。保持后續的打印數字m[i]遞減。
這道題的c代碼:
/** 最長非降子序列* * m[i] = MAX(m[j]) + 1; a[i] > a[j] && j < i;*/#include <stdio.h> #include <time.h> #include <stdlib.h>#define MAX(a, b) ((a) > (b) ? (a) : (b))void main() {int a[30] = {0}, n, i,j,k,max,m[30] = {0}, c[30];printf("input total numbers :"); scanf("%d", &n);if (n > 30){printf("invalid number\n");return;}//隨機生成一些數字srand(time(NULL));for (i = 0; i < n; i++)a[i] = rand()%20 + 1;printf("無序數列為:");for (i = 0; i < n; i++)printf("%d ", a[i]);printf("\n"); //邊界初始化m[n-1] = 1;c[n-1] = n-1;//狀態遞推for (i = n- 2; i >= 0; i--){m[i] = 1;c[i] = i;for (j = n - 1; j > i; j--){if (a[i] <= a[j]){if (m[i] < m[j] + 1){m[i] = m[j] + 1; c[i] = j;}} }}//打印最優值max = 0;for (i = 0; i < n; i++){ //printf("%d ", m[i]);if (m[i] > max){max = m[i];k = i;}} printf("最長非降子數列長度為:%d\n", max);while (c[k] != k){printf("%d ", a[k]);k = c[k];}printf("%d \n",a[k]);return; }?
參考資料:
1.?數據結構?: C語言版/ 嚴蔚敏,吳偉民編著
=============================================================================================
Linux應用程序、內核、驅動開發交流討論群(745510310),感興趣的同學可以加群討論、交流、資料查找等,前進的道路上,你不是一個人奧^_^。
 ?
總結
以上是生活随笔為你收集整理的动态规划 dp02 最长非降子序列问题 c代码的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 简单选择排序 c代码
- 下一篇: 动态规划 dp03 最长公共子串问题 c
