Nguồn đề bài: http://vn.spoj.com/problems/LIQ/
1. Đề bài LIQ Dãy con tăng dài nhất
Cho một dãy số nguyên gồm N phần tử A[1], A[2], … A[N].
Biết rằng dãy con tăng đơn điệu là 1 dãy A[i1],… A[ik] thỏa mãn
i1 < i2 < … < ik và A[i1] < A[i2] < .. < A[ik]. Hãy cho biết dãy con tăng đơn điệu dài nhất của dãy này có bao nhiêu phần tử?
Download test và solution (C/C++, Pascal) tại đây.
Input
- Dòng 1 gồm 1 số nguyên là số N (1 ≤ N ≤ 1000).
- Dòng thứ 2 ghi N số nguyên A[1], A[2], .. A[N] (1 ≤ A[i] ≤ 10000).
Output
Ghi ra độ dài của dãy con tăng đơn điệu dài nhất.
Ví dụ
Input:
6
1 2 5 4 6 2
Output:
4
Giải thích test ví dụ: Dãy con dài nhất là dãy A[1] = 1 < A[2] = 2 < A[4] = 4 < A[5] = 6, độ dài dãy này là 4.
Gợi ý: Sử dụng phương pháp Quy Hoạch Động. F[i]: Độ dài dãy con đơn điệu tăng dài nhất mà phần tử cuối cùng là số A[i] này.
2. Hướng dẫn LIQ SPOJ Dãy con tăng dài nhất
– Gọi F[i] là độ dài dãy con tăng dần dài nhất kết thúc tại i
– khởi tạo F[i]=1; (với i=1..n)
– F[i]=max(F[i],F[j]+1) (A[i]>A[j] ; i=1..n, j=1..i-1).
– nghiệm bài toán Max(F[i]) (i=1..n)
3. Code tham khảo LIQ SPOJ Dãy con tăng dài nhất
a. Code Pascal
const fi=''; nmax=1000; type data=longint; var f:text; A,B:array[0..nmax+1] of data; n:data; procedure docfile; var i,j:data; begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do read(f,a[i]); close(f); end; function max(a,b:data):data; begin if a>b then exit(a); exit(b); end; procedure qhd; var i,j,res:data; begin res:=1; for i:=1 to n do begin b[i]:=1; for j:=1 to i-1 do if A[i]>a[j] then b[i]:=max(b[i],b[j]+1); res:=max(res,b[i]); end; writeln(res); end; begin docfile; qhd; end.
b. code c++
#include <stdio.h> #include <algorithm> using namespace std; #define nmax=1000 int n; int a[1000], f[1000]; int main() { scanf("%d",&n); int i,j; for (i=1; i<=n; i++) { scanf("%d",&a[i]); f[i]=1; } for (i=1; i<=n; i++) { for (j=i+1; j<=n; j++) { if (a[i]<a[j]) f[j]=max(f[i]+1,f[j]); } } int res=0; for (i=1; i<=n; i++) res=max(res,f[i]); printf("%d",res); return 0; }