1.最大子序列和
题目链接:This is the link
题目代码:
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x7f7f7f7f //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
#define MAX 100000
int num[MAX+5];
int dp[MAX+5];
int main()
{
int T;
scanf("%d",&T);
for(int k=1; k<=T; k++)
{
int n,begin,end;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&num[i]);
int maxn=-INT_INF;//必须小于-1001,注意
for(int i=1; i<=n; i++)
{
dp[i]=max(num[i],dp[i-1]+num[i]);
if(maxn<dp[i])
{
maxn=dp[i]; //更新最大值
end=i; //记录最后数的位置
}
}
int sum=maxn;
for(int i=end; i>0; i--)
{
sum-=num[i];
if(!sum)
begin=i;//最长的子序列,加break可以最短子序列,注意
}
printf("Case %d:\n%d %d %d\n",k,maxn,begin,end);
if(k<T)//注意,输出格式
printf("\n");
}
return 0;
}
2.最长上升子序列(Longest Increasing Subsequence,LIS)
题目链接:This is the link
题目代码:(n*n的时间复杂度)
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x7f7f7f7f //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
int a[1005];
int dp[10005];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",a+i);
dp[0]=1;//第一个元素的长度为1
int maxn=1;
for(int i=1;i<n;++i)
{
dp[i]=1;//初始化为1
for(int j=0;j<i;++j)
{
if(a[i]>a[j]&&dp[j]+1>dp[i])//当前元素的大小大于前面的,并且长度小小于前面的
dp[i]=dp[j]+1;//更新长度
}
maxn=max(maxn,dp[i]);
}
printf("%d\n",maxn);
return 0;
}
二分优化(nlongn)
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include <iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x7f7f7f7f //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
int a[1005];
int dp[1005];
int find(int m,int x)
{
int l=1,r=m;
int mid;
while(l<r)
{
mid=(l+r)>>1;
if(x>dp[mid])
l=mid+1;
else
r=mid;
}
return l;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
int tot=1;
dp[1]=a[1];
for(int i=2;i<=n;++i)
{
if(a[i]>=dp[tot])
dp[++tot]=a[i];
else
dp[find(tot,a[i])]=a[i];
}
cout<<tot<<endl;
return 0;
}
3.最长公共子序列(LCS)
// luogu-judger-enable-o2
#include<iostream>
#include<algorithm>
using namespace std;
int s1[100005],s2[100005];
int dp[10005][10005];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;++i)
cin>>s1[i];
for(int i=1;i<=n;++i)
cin>>s2[i];
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(s1[i]==s2[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[n][n];
return 0;
}
4.最长上升公共子序列(LCIS)
hdu1423 This is the link
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long lld;
const int oo=0x3f3f3f3f;
const lld OO=1LL<<61;
const lld MOD=1000000007;
#define eps 1e-6
#define maxn 505
int dp[maxn][maxn];
int path[maxn][maxn];
int a[maxn],b[maxn];
int n,m;
/*本题不需要输出序列
void dfs(int x)//输出序列
{
if(path[n][x]==-1)
{
printf("%d",b[x]);
return ;
}
dfs(path[n][x]);
printf(" %d",b[x]);
}
*/
int main()
{
int t;
scanf("%d",&t);
for(int k=1;k<=t;++k)
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1; i<=m; i++)
scanf("%d",&b[i]);
memset(dp,0,sizeof dp);
memset(path,-1,sizeof path);
for(int i=1; i<=n; i++)//实现过程
{
int pos=-1,Max=0;
for(int j=1; j<=m; j++)
{
dp[i][j]=dp[i-1][j];
path[i][j]=path[i-1][j];
if(a[i]==b[j]&&dp[i][j]<Max+1)
{
dp[i][j]=Max+1;
path[i][j]=pos;
}
if(a[i]>b[j]&&dp[i-1][j]>Max)
{
Max=dp[i-1][j];
pos=j;
}
}
}
int ans=1;
for(int i=1; i<=m; i++)
if(dp[n][ans]<dp[n][i])
ans=i;
printf("%d\n",dp[n][ans]);//格式要求很严
if(k<t)
puts("");//输出换行
/*本题不需要输出序列
if(dp[n][ans])
dfs(ans);
puts("");//换行
*/
}
return 0;
}