基础DP(4)
- 最长递增子序列(LIS)
http://120.78.128.11/Problem.jsp?pid=1388
http://acm.hdu.edu.cn/showproblem.php?pid=1257
最长递增子序列,例如X={5,6,7,4,2,8,3},它的最长递增子序列为{5,6,7,8},长度为4。
题目上是需要求单调递减子序列最少有多少个,按照LIS的思想,只用把递增改为递减即可。
定义dp[i],用它来表示以第i个数为结尾的最长递增子序列的长度,得到状态方程:dp[i]=max(0,dp[j])+1。(0<j<i,Aj<Ai)
代码1:
#include<stdio.h> #include<algorithm> using namespace std; int n,cnt; int a[10005],b[10005]; int main(void) { while(~scanf("%d",&n)){ cnt=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=1; for(int j=1;j<=i;j++){ if(a[j]<a[i]) b[i]=max(b[i],b[j]+1); cnt=max(cnt,b[i]); } } printf("%d\n",cnt); } }
代码2:
#include<bits/stdc++.h> using namespace std; const int MAXN=10000; int n,high[MAXN]; int LIS(){ int cnt=1; int dp[MAXN]; dp[1]=1; for(int i=2;i<=n;i++){ int max=0; for(int j=1;j<i;j++){ if(dp[j]>max&&high[j]<high[i]) max=dp[j]; } dp[i]=max+1; if(dp[i]>cnt) cnt=dp[i]; } return cnt; } int main() { while(cin>>n){ for(int i=1;i<=n;i++){ cin>>high[i]; } cout<<LIS()<<endl; } return 0; }
要求输出具体方案时,同样可以用滚动数组减少空间复杂度,和0/1背包相同。
码一点基础DP题~
背包:
http://acm.hdu.edu.cn/showproblem.php?pid=2159
http://acm.hdu.edu.cn/showproblem.php?pid=2844
http://acm.hdu.edu.cn/showproblem.php?pid=3092
http://poj.org/problem?id=1015
http://poj.org/problem?id=1170
LIS:
http://acm.hdu.edu.cn/showproblem.php?pid=1003
http://acm.hdu.edu.cn/showproblem.php?pid=1087
http://acm.hdu.edu.cn/showproblem.php?pid=4352
http://poj.org/problem?id=1239
LCS:
http://acm.hdu.edu.cn/showproblem.php?pid=1503
http://poj.org/problem?id=1080
EOF