## lis問題及其應用
模板
這裡給出貪心+二分(n log n),dp(n²)兩種做法。
//動態規劃o(n²)
#include
#include
using
namespace std;
int n;
const
int max=
1010
;int a[max]
;int dp[max]
;int
main()
int res=0;
for(
int i=
1;i<=n;i++
) res=
max(res,dp[i]);
cout
}
#include
#include
using
namespace std;
int n;
const
int max=
10010
;int a[max]
,t[max]
;int
main()
t[r+1]
=a[i]
; len=
max(len,r+1)
;}cout
}
雙向lis
#include
#include
#include
using
namespace std;
int dp[
1001];
int a[
1001];
intmain()
for(
int i=
1;i<=n;i++
) result=
max(result,dp[i]);
}for
(int i=n;i>=
1;i--
) result=
max(result,dp[i]);
}printf
("%d\n"
,result);}
return0;
}
爆搜+lis
思路:預處理出以每個點為結尾的lis,和以每個點為開頭的下降序列。再通過暴力列舉出每一種情況。
#include
#include
#include
using
namespace std;
int n;
const
int max=
1100
;int high[max]
,higher[max]
,lower[max]
,res=0;
intmain()
}for
(int i=n;i;i--)}
for(
int i=
1;i<=n;i++
) res=
max(res,higher[i]
+lower[i]-1
);cout
}
合唱隊形(爆搜+lis)
思路:要想剔除的人最少,就需要對留下的人最多。根據題意,每個佇列都會有乙個中間點。(這個點左邊的點比他小,右邊的點比他大),那麼我們先預處理出以每個點作為中間點時,比它小的點的個數和比他大的點的個數。用上一題的做法求出佇列中最多剩下的人數之後,再用n(總共的人數)-這個數 就是答案。
#include
#include
#include
using
namespace std;
int n;
const
int max=
110;
int a[max]
;int higher[max]
,lower[max]
;int
main()
for(
int i=n;i;i--
)int res=0;
for(
int i=
1;i<=n;i++
) res=
max(res,lower[i]
+higher[i]-1
);cout
}
友好城市 轉換題lis+sort
思路: 本題的做法是先按照其友好城市的座標sort一遍,再做一遍lis。 接下來說明為什麼要這麼做:
1.友好城市之間的線路不能交叉,就代表著兩個友好城市的座標必須同時單調遞增。
2.再加上要求最多的城市對數,很容易想到要使用最長上公升子串行。既然要兩者同時保持單調性(自然可以基於其友好城市對其進行排序,兩個城市同時lis應該也可以)。
3.最後一邊lis就是答案。
//經過這一題,要注意演算法題中單調性,無論是條件還是特性都十分重要。
#include
#include
using
namespace std;
typedef pair<
int,
int> pii;
int n;
const
int max=
5100
;int dp[max]
;pii a[max]
;int
main()
sort
(a+1
,a+n+1)
;int res=0;
for(
int i=
1;i<=n;i++
) res=
max(dp[i]
,res);}
cout
}
lisdp思想運用 最大上公升子串行和
//dp的思想和考慮方式和lis問題一樣。
#include
#include
using
namespace std;
int n;
const
int max=
10010
;int a[max]
,dp[max]
;int
main()
res=
max(res,dp[i]);
} cout
}
lis問題性質的探索 dilworth定理
//關於lis問題有乙個非常有趣的性質:把整個序列用其下降子串行填滿需要的上公升子串行數=該序列的最長上公升子串行。
(類似,用上公升子串行填滿就=最長下降子串行長度)
#include
#include
#include
using
namespace std;
const
int max=
10010
;int a[max]
,up[max]
,down[max]
;int
main()
res1=
max(up[i]
,res1)
; res2=
max(res2,down[i]);
} cout
}
動態規劃 之 最長上公升子串行
乙個數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2,an 我們可以得到一些上公升的子串行 ai1,ai2,aik 這裡1 i1 i2 ik n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等。這些子串...
動態規劃之最長上公升子串行
北大郭煒老師講的能採用動態規劃求解問題的特點 1 問題具有最優子結構的性質 2 無後效性。實現動態規劃的三個步驟 1 講原問題分解為子問題 2 確定狀態以及初始狀態 邊界值 3 狀態轉移方程 人人為我 遞推型 第一步的子問題就是a i 為終點的最長上公升子串行。include includeusin...
動態規劃之最長上公升子串行
動態規劃指的是將乙個繁雜的問題分解成子問題之後,通過求解子問題的最優解,從而求得整體最優解。輸入資料 輸入的第一行是序列的長度n 1 n 1000 第一行給出序列的n個整數,這些整數的取值範圍在0 10000.輸出要求 最長上公升子串行的長度。輸入樣例 7 1 7 3 5 9 4 8 輸出樣例 範例...