記一次360靶場考核
阿新 • • 發佈:2021-11-18
例一:求最長上升序列
題目描述
設有由n個不相同的整陣列成的數列,記為:b(1)、b(2)、……、b(n)且b(i)<>b(j) (i<>j),若存在i1<i2<i3< … < ie 且有b(i1)<b(i2)< … <b(ie)則稱為長度為e的不下降序列。程式要求,當原數列出之後,求出最長的上升序列。
例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一個長度為7的不下降序列,同時也有7 ,9,16,18,19,21,22,63長度為8的不下降序列。
輸入格式
只有一行,為若干正整數(最多1000個數)
輸出格式
為兩行,第一行為最上升序列的長度。 第二行為該序列
樣例
樣例輸入
13 7 9 16 38 24 37 18 44 19 21 22 63 15
樣例輸出
max=8
7 9 16 18 19 21 22 63
兩種方法其實也沒什麼本質上的區別
法一
#include<bits/stdc++.h> using namespace std; int a,count1=0,max1=0,maxi,ans[1005],count2=0; struct str{ int b; int f; int before; }q[1005]; int main (){ while(cin>>a){ q[++count1].b=a; q[count1].f=1;//F(i)為b[1.....i]中的最長上升子序列長度(以b[i]為結尾) } for(int i=2;i<=count1;i++){ for(int j=1;j<i;j++){ if(q[i].b>q[j].b&&q[i].f<q[j].f+1){ q[i].f=q[j].f+1; q[i].before=j;//before(j)記錄與a[i]相連的上一個下標--記錄路徑 } } if(q[i].f>max1){ max1=q[i].f; maxi=i; } } cout<<"max="<<max1<<endl; for(;maxi>=1;maxi=q[maxi].before){ ans[++count2]=maxi; } for(int i=count2;i>=1;i--){ cout<<q[ans[i]].b<<" "; } return 0; }
法二
#include<bits/stdc++.h> using namespace std; int n,x,max1,l; int a[1005],before[1005],dp[1005],ans[1005]; void input(){ while(cin>>x){ a[++n]=x; dp[n]=1; } //cout<<"@@@"<<n<<endl; } void success(){ for(int i=2;i<=n;i++){ for(int j=1;j<i;j++){ if(a[j]<a[i]&&dp[j]>dp[before[i]]){//j不僅要比i大,盲點:::更要找連線最多的 before[i]=j; dp[i]=dp[j]+1; } //else dp[i]=dp[i]; } } } void output(){ max1=0;dp[max1]=0; for(int i=1;i<=n;i++){ // cout<<dp[i]<<endl; if(dp[i]>dp[max1]) max1=i;//尋找最大dp值下標 } cout<<"max="<<dp[max1]<<endl; for(;max1>=1;max1=before[max1]){ ans[++l]=max1;//ans 存下標 } for(int i=l;i>=1;i--){ cout<<a[ans[i]]<<" "; } } int main (){ input(); success(); output(); return 0; }