赞
踩
目录
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- #include<bits/stdc++.h>
- using namespace std;
- const int N=1e3+10;
- int f[N],a[N];
- int main()
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>a[i];
- for(int i=1;i<=n;i++)
- {
- f[i]=1;//表示只有自己一个数的时候
- for(int j=1;j<i;j++)
- if(a[j]<a[i])//假如这个位置上的数比我小
- f[i]=max(f[i],f[j]+1);//则进行状态转移
- ans=max(ans,f[i]);//更新一下以每个数结尾的最长上升子序列的最大值
- }
- cout<<ans<<endl;
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- //因为是从一个点可以飞两个方向,故求正向求一次最长上升子序列,逆向也求一次,最后取最大值
- #include<bits/stdc++.h>
- using namespace std;
- const int N=110;
- int h[N],f[N];
- int main()
- {
- int t;
- cin>>t;
- while(t--)
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>h[i];
- //正向求一次最长上升子序列
- for(int i=1;i<=n;i++)
- {
- f[i]=1;
- for(int j=1;j<i;j++)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- ans=max(f[i],ans);//更新最大值
- }
- //逆向求一次最畅销上升子序列
- for(int i=n;i;i--)
- {
- f[i]=1;
- for(int j=n;j>i;j--)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- ans=max(f[i],ans);//更新最大值
- }
- cout<<ans<<endl;
- }
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- #include<bits/stdc++.h>
- using namespace std;
- const int N=1e3+10;
- int h[N],f[N];//f存的是以i结尾的最长上升子序列
- int main()
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>h[i];
- //正向求一次最长上升子序列
- for(int i=1;i<=n;i++)
- {
- f[i]=1;
- for(int j=1;j<i;j++)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- }
- //逆向求一次最长上升子序列
- for(int i=n;i;i--)
- {
- int flag=f[i];//先把正向的最长上升子序列记录下来
- f[i]=1;//在从新求逆向的最长上升子序列
- for(int j=n;j>i;j--)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- ans=max(f[i]+flag-1,ans);//更新一下两个和的最大值,因为第i这个数被加了两次1,故结果得减一
- }
- cout<<ans<<endl;
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
题意跟登山一模一样,只是结果要的是去掉的人
- #include<bits/stdc++.h>
- using namespace std;
- const int N=1e3+10;
- int h[N],f[N];//f存的是以i结尾的最长上升子序列
- int main()
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>h[i];
- //正向求一次最长上升子序列
- for(int i=1;i<=n;i++)
- {
- f[i]=1;
- for(int j=1;j<i;j++)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- }
- //逆向求一次最长上升子序列
- for(int i=n;i;i--)
- {
- int flag=f[i];//先把正向的最长上升子序列记录下来
- f[i]=1;//在从新求逆向的最长上升子序列
- for(int j=n;j>i;j--)
- if(h[j]<h[i])
- f[i]=max(f[i],f[j]+1);
- ans=max(f[i]+flag-1,ans);//更新一下两个和的最大值,因为第i这个数被加了两次1,故结果得减一
- }
- cout<<n-ans<<endl;//结果要去掉的人
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- #include<bits/stdc++.h>
- using namespace std;
- typedef pair<int,int> pii;
- const int N=5010;
- int f[N];
- pii he[N];//存两边对应的友好城市
- int main()
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++)
- {
- int a,b;
- cin>>a>>b;
- he[i]={a,b};
- }
- sort(he+1,he+n+1);//按北岸的城市排序
- //求一下南岸的最长上升子序列
- for(int i=1;i<=n;i++)
- {
- f[i]=1;
- for(int j=1;j<i;j++)
- if(he[j].second<he[i].second)
- f[i]=max(f[i],f[j]+1);
- ans=max(ans,f[i]);
- }
- cout<<ans<<endl;//输出南岸的最长上升子序列,也就是最大不相交数
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- #include<bits/stdc++.h>
- using namespace std;
- typedef pair<int,int> pii;
- const int N=1e3+10;
- int f[N],a[N];
- int main()
- {
- int n,ans=0;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>a[i];
- for(int i=1;i<=n;i++)
- {
- f[i]=a[i];//空的时候,只有自己
- for(int j=1;j<i;j++)
- if(a[j]<a[i])//假如这个数小于当前数
- f[i]=max(f[i],f[j]+a[i]);//进行状态转移
- ans=max(ans,f[i]);//更新一下最大值
- }
- cout<<ans<<endl;
- return 0;
- }
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
- #include<bits/stdc++.h>
- using namespace std;
- const int N=1e3+10;
- int a[N],q[N],f[N];
- int main()
- {
- int n=0;
- while(cin>>a[n]) n++;
- int ans=0;
- //求最长上升子序列
- for(int i=0;i<n;i++)
- {
- f[i]=1;
- for(int j=0;j<i;j++)
- if(a[j]>=a[i])
- f[i]=max(f[i],f[j]+1);
- ans=max(f[i],ans);
- }
- cout<<ans<<endl;
- //求覆盖次数,贪心
- int cnt=0;
- for(int i=0;i<n;i++)
- {
- int k=0;
- while(k<cnt&&q[k]<a[i]) k++;//找现有序列中大于当前数的最小的数
- q[k]=a[i];//更新一下当前数
- if(k>=cnt) cnt++;//否则开辟新的子序列
- }
- cout<<cnt;
- return 0;
- }
跟拦截导弹的贪心一样,多了dfs
- #include<bits/stdc++.h>
- using namespace std;
- const int N=60;
- int a[N],up[N],down[N];
- int ans=0,n;
- void dfs(int u,int su,int sd)//u表示当前数,su表示上升子序列的数量,sd表示下降子序列的数量
- {
- if(su+sd>=ans) return;//加入当前的次数比最小值还大,则return
- if(u==n)//否则到了末尾,更新最小值
- {
- ans=su+sd;
- return;
- }
- //假如加到上升子序列中
- int k=0;
- while(k<su&&up[k]>=a[u]) k++;
- int t=up[k];//把当前数存下来,用来回溯
- up[k]=a[u];//更新当前的末尾
- if(k<su) dfs(u+1,su,sd);//假如不需要开辟新子序列
- else dfs(u+1,su+1,sd);//假如开辟新子序列
- up[k]=t;//回溯
- //假如加到下降子序列中,做法与上升相同,只不过把大于等于改小于等于
- k=0;
- while(k<sd&&down[k]<=a[u]) k++;
- t=down[k];
- down[k]=a[u];
- if(k<sd) dfs(u+1,su,sd);
- else dfs(u+1,su,sd+1);
- down[k]=t;
- }
- int main()
- {
- while(cin>>n,n)
- {
- for(int i=0;i<n;i++) cin>>a[i];
- ans=n;
- dfs(0,0,0);
- cout<<ans<<endl;
- }
- return 0;
- }
- #include<bits/stdc++.h>
- using namespace std;
- const int N=3010;
- int a[N],b[N],f[N][N];
- int main()
- {
- int n,ans=0;
- scanf("%d",&n);
- for(int i=1;i<=n;i++) scanf("%d",&a[i]);
- for(int i=1;i<=n;i++) scanf("%d",&b[i]);
- for(int i=1;i<=n;i++)
- for(int j=1;j<=n;j++)
- {
- f[i][j]=f[i-1][j];//所有不包含a[i]的最长公共上升子序列
- if(a[i]==b[j])//所有包含a[i]的最长公共上升子序列
- {
- f[i][j]=max(f[i][j],1);//当空的时候是自己,也就是1
- for(int k=1;k<j;k++)//求最长公共上升子序列
- if(b[k]<b[j])
- f[i][j]=max(f[i][j],f[i][k]+1);
- }
- }
- //求最大值,第一个序列的前n个字母,与b的匹配最大
- for(int i=1;i<=n;i++) ans=max(ans,f[n][i]);
- printf("%d\n",ans);
- return 0;
- }
- #include<bits/stdc++.h>
- using namespace std;
- const int N=3010;
- int a[N],b[N],f[N][N];
- int main()
- {
- int n;
- scanf("%d",&n);
- for(int i=1;i<=n;i++) scanf("%d",&a[i]);
- for(int i=1;i<=n;i++) scanf("%d",&b[i]);
- for(int i=1;i<=n;i++)
- {
- int maxf=1;//由于在k中重复求前j个最大值,所有用一个maxf记录前j个的最长上升子序列的最大值
- for(int j=1;j<=n;j++)
- {
- f[i][j]=f[i-1][j];//所有不包含a[i]的最长公共上升子序列
- if(a[i]==b[j]) f[i][j]=max(f[i][j],maxf);//所有包含a[i]的最长公共上升子序列,更新最大值
- if(b[j]<a[i]) maxf=max(maxf,f[i][j]+1);//因为a[i]==b[j]的时候更新最大值,所以可以把b[j]换成a[i],用来与新的b[j]比较
- }
- }
- //最后更新一遍最大值
- int ans=0;
- for(int i=1;i<=n;i++) ans=max(ans,f[n][i]);
- printf("%d\n",ans);
- return 0;
- }
- #include<bits/stdc++.h>
- using namespace std;
- const int N=3010;
- int a[N],b[N],f[N];
- int main()
- {
- int n,ans=0;
- scanf("%d",&n);
- for(int i=1;i<=n;i++) scanf("%d",&a[i]);
- for(int i=1;i<=n;i++) scanf("%d",&b[i]);
- for(int i=1;i<=n;i++)
- for(int j=1,maxf=1;j<=n;j++)
- {
- //因为更新f[i][j]的时候只用到了上一维f[i-1][j]的信息,故可以优化变成一维
- if(a[i]==b[j]) f[j]=max(f[j],maxf);
- if(b[j]<a[i]) maxf=max(maxf,f[j]+1);
- }
- //求一遍最大值
- for(int i=1;i<=n;i++) ans=max(ans,f[i]);
- printf("%d\n",ans);
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。