动态规划-最长不下降子序列
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 101 #define MAX 1<<30 #define V vector<int> using namespace std; int a[LEN]; int dp[LEN]; int n; void printAns(int cnt,int pos,V vec){ vec.insert(vec.begin(),a[pos]); int obj=dp[pos--]-1; while(pos>0){ if(dp[pos]==obj) printAns(cnt-1,pos,vec); pos--; } if(cnt==1){ int i; FF(i,vec.size()) O("%d ",vec[i]); OL(""); } } void DP_n2(){ int i,j,p; int ans=0; F(i,1,n+1){ dp[i]=1; F(j,1,i){ if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1); } if(dp[i]>ans){ ans=dp[i]; p=i; } } O("ans=%d p=%d\n序列 :\n",ans,p); F(i,1,n+1)O("%d ",a[i]) ; OL("\nDP数组 :"); F(i,1,n+1)O("%d ",dp[i]) ; OL(""); V vec; OL("所有LIS :"); printAns(ans,p,vec); } void DP_nLogn(){ int i,j,top=0; F(i,1,n+1){ if(top==0 || dp[top-1]<a[i]) dp[top++]=a[i]; else{ int pos=lower_bound(dp,dp+top,a[i])-dp; dp[pos]=a[i]; } } printf("%d\n",top); OL("DP数组: "); F(i,0,top)O("%d ",dp[i]); OL("\n") ; } int main() { //dilworth定理:LIS 长度 等于 LIS 子序列 个数 freopen("LIS.txt","r",stdin); int i,j; I("%d",&n); F(i,1,n+1){ I("%d",&a[i]); } DP_nLogn(); DP_n2(); return 0; }
测试数据:
11 1 3 7 6 8 5 3 2 7 2 9
OJ:导弹拦截
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 100001 #define MAX 1<<30 #define V vector<int> using namespace std; int a[LEN]; int dp1[LEN];//increase int dp2[LEN];//decrease bool cmp(int x,int y){ return x>y; } int main(){ freopen("D:/CbWorkspace/动态规划/导弹拦截.txt","r",stdin); int i,n=0; while(I("%d",&a[++n])>0); n--; fill(dp2,dp2+n+1,MAX); int len1=0,len2=0; F(i,1,n+1){ //记录递增dp int p1=upper_bound(dp1+1,dp1+1+n,a[i],cmp)-dp1; //在递减序列中进行操作 //记录递减dp(初始化Inf) int p2=lower_bound(dp2+1,dp2+1+n,a[i])-dp2; //在递增序列中进行操作 dp1[p1]=a[i] ; dp2[p2]=a[i] ; len1=max(len1,p1); len2=max(len2,p2); int s=0; } O("%d\n%d",len1,len2); return 0; }
OJ : 合唱队形
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 100001 #define MAX 1<<30 #define V vector<int> using namespace std; int dp1[LEN] ; int dp2[LEN] ; int a[LEN] ; int max1[LEN] ; int max2[LEN] ; bool cmp(int x,int y){ return x>y; } int main(){ // freopen("D:/CbWorkspace/动态规划/合唱队形.txt","r",stdin); int n,i,j; I("%d",&n); FF(i,n) I("%d",&a[i]); int max_ans=0; FF(i,n){ dp1[i]=1; FF(j,n){ if(a[j]<a[i]){ dp1[i]=max(dp1[i],dp1[j]+1); } } max_ans=max(max_ans,dp1[i]); max1[i]=max_ans; } max_ans=0; for(i=n-1;i>=0;i--){ dp2[i]=1; for(j=n-1;j>i;j--){ if(a[i]>a[j]){ dp2[i]=max(dp2[i],dp2[j]+1); } } max_ans=max(max_ans,dp2[i]); max2[i]=max_ans; } int ans=0; FF(i,n-1){ int t=max1[i]+max2[i+1]; ans=max(ans,t); } O("%d",n-ans); return 0; }