拿poj 2533來說。
sample input 7
1 7 3 5 9 4 8
sample output 4
從輸入的序列中找出最長的上公升子串行(lis)。
這題一看,是一道典型的dp問題(就是動態規劃),可以用dfs,深度優先遍歷來解,如下**:
#include
#include
using namespace std;
int n;
int* a;
stacks;
int count=0;
int best=0;
void dfs(int i)
if(s.empty()||a[i]>s.top())
if(s.size()+n-i-1>best) dfs(i+1);
} int main()
dfs(0);
cout<}
return 0;
}其實為了簡化**以及演算法效率,我們可以用資料組來代替遞迴。。。下面我就給出lis的dp的資料組形式的解法:
(懶得寫了,就拿個別人的**來展示吧)
#include
#define size 1001
using namespace std;
int main()
max = 0;
for (i = 1; i <= n; i++)
}/* 記錄最長子序列 */
if (d[i] > max) max = d[i];
}cout << max << endl;
}//system("pause");
return 0;
}(作者的解釋:)令a[i]表示輸入第i個元素,d[i]表示從a[1]到a[i]中以a[i]結尾的最長子序列長度。對於任意的0 < j <= i-1,如果a(j) < a(i),則a(i)可以接在a(j)後面形成乙個以a(i)結尾的新的最長上公升子串行。對於所有的 0 < j <= i-1,我們需要找出其中的最大值。
dp狀態轉移方程:
d[i] = max (j = 1, 2, 3, ..., i-1 且 a[j] < a[i])
解釋一下這個方程,i, j在範圍內:
如果 a[j] < a[i] ,則d[i] = d[j] + 1
如果 a[j] >= a[i] ,則d[i] = 1
其實上面的方法的複雜度都達到了o(n^2)的數量級,有沒有更好的解法呢?
有,用棧。
這個解法不是我想的,從網上學來的,這裡面與大家分享一下。這個演算法的複雜度只有o(nlogn),在有大量資料的情況下,這演算法效率極高。。。
(摘錄原作者的話)
這個演算法其實已經不是dp了,有點像貪心。至於複雜度降低其實是因為這個演算法裡面用到了二分搜尋。本來有n個數要處理是o(n),每次計算要查詢n次還是o(n),一共就是o(n^2);現在搜尋換成了o(logn)的二分搜尋,總的複雜度就變為o(nlogn)了。
這個演算法的具體操作如下(by ryanwang):
開乙個棧,每次取棧頂元素top和讀到的元素temp做比較,如果temp > top 則將temp入棧;如果temp < top則二分查詢棧中的比temp大的第1個數,並用temp替換它。 最長序列長度即為棧的大小top。
這也是很好理解的,對於x和y,如果x < y且stack[y] < stack[x],用stack[x]替換stack[y],此時的最長序列長度沒有改變但序列q的''潛力''增大了。
舉例:原序列為1,5,8,3,6,7
棧為1,5,8,此時讀到3,用3替換5,得到1,3,8; 再讀6,用6替換8,得到1,3,6;再讀7,得到最終棧為1,3,6,7。最長遞增子串行為長度4。
我想,當出現1,5,8,2這種情況時,棧內最後的數是1,2,8不是正確的序列啊?難道錯了?
分析一下,我們可以看出,雖然有些時候這樣得不到正確的序列了,但最後算出來的個數是沒錯的,為什麼呢?
想想,當temp>top時,總個數直接加1,這肯定沒錯;但當temp
用該演算法完成poj2533的具體**如下:
#include#define size 1001
using namespace std;
int main(
)else
else
}/* 用temp替換 */
stack[low]
= temp;}}
/* 最長序列數就是棧的大小 */
cout
<< top << endl;
} return0;
}
最長上公升子串行問題的幾種解法
拿poj 2533來說。sample input 7 1 7 3 5 9 4 8 sample output 從輸入的序列中找出最長的上公升子串行 lis 這題一看,是一道典型的dp問題 就是動態規劃 可以用dfs,深度優先遍歷來解,如下 include include using namespac...
最長上公升子串行問題的幾種解法
拿poj 2533來說。sample input 7 1 7 3 5 9 4 8 sample output 從輸入的序列中找出最長的上公升子串行 lis 這題一看,是一道典型的dp問題 就是動態規劃 可以用dfs,深度優先遍歷來解,如下 include include using namespac...
最長上公升子串行(Python and C 解法)
給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。示例 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行是 2,3,7,101 它的長度是 4。說明 子串行不同於子串,可以不連續。採用動態規劃。定義狀態 dp i 表示以 nums i 這個數為結尾的最長遞增子串...