华师一附中OI组
标题:
最长不下降序列LICS
[打印本页]
作者:
diggersun
时间:
2015-10-31 20:42
标题:
最长不下降序列LICS
题目:给定一个序列,求它的一个子序列,保证后面一个数字不小于前面的数字,并且最长。
比如 1 3 5 9 7 8 6 4 2 0 这个序列,1 3 5 7 8 是它的一个子序列,长度为5,后面的数字不小于前面的数字,并且,找不到比它更长的。
作者:
diggersun
时间:
2015-10-31 20:46
我上课时候讲的是标准做法,虽然略有一点繁琐,但是清晰,扩展性强,同学们要认真去理解。虽然有的书上或者网上讲的比我的简单,但是,损失了一点扩展性,等熟练之后大家也可以学习网上的做法。
思路:用a数组表示每个数字的值,l数字表示目前最大的长度,f数组表示这个数字的前驱,p数组表示路径。
#include<iostream>
#include<iomanip>
using namespace std;
int a[11]= {0,1,7,3,5,9,2,8,6,4,99}; //假设有9个数字分别是1,7,3,5,9,2,8,6,4,第一个位子空着,最后一个是假标记
int l[11]; //到当前为止的最长不下降序列的长度
int f[11]; //当前最优决策时的前驱的编号
int p[11];//输出路径时用的数组
int i,j;
int main()
{
for (i=0; i<=10; i++)
{
l[i]=1; //至少的长度是1
f[i]=-1; //不需要前驱
}
for(i=2; i<=10; i++) ///枚举当前位置
for (j=1; j<i; j++) ///枚举当前位置前面的所有可能
if (a[j]<=a[i]) ///不下降
if (l[j]+1>=l[i]) ///最长
{
l[i]=l[j]+1; ///决策
f[i]=j; ///记录前驱
}
for (i=0; i<=10; i++)
cout<<setw(4)<<a[i];
cout<<endl;
for (i=0; i<=10; i++)
cout<<setw(4)<<l[i];
cout<<endl;
for (i=0; i<=10; i++)
cout<<setw(4)<<f[i];
cout<<endl;
i=0;
p[i]=10; ///最后一个绝对是最长的
while (f[p[i]]!=-1) ///还有前驱
{
i++;
p[i]=f[p[i-1]];
}
for (j=i; j!=-1; j--) cout<<a[p[j]]<<' '; ///输出最后的路径
return 0;
}
复制代码
作者:
diggersun
时间:
2015-10-31 20:46
上面的做法很直观但是浪费也是很严重的,怎么改进呢
作者:
diggersun
时间:
2015-10-31 20:46
diworth定理
作者:
SilverMOR
时间:
2016-2-17 14:34
那么然后呢
作者:
张笑宇
时间:
2018-7-27 21:28
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[10010],d[10010],len;
int main()
{
cin>>n;
for (int i=1; i<=n; i++) cin>>a[i];
len=1,d[1]=a[1];
for (int i=2; i<=n; i++)
{
if (a[i]>=d[len])///不下降
d[++len]=a[i];
else
{
int l=0,r=len,mid;
while (l<r)
{
mid=(r-l)/2+l;
if (d[mid]>a[i]) r=mid;
else l=mid+1;
}
d[l]=a[i];
}
}
cout<<len;
return 0;
}
复制代码
作者:
黄煦喆
时间:
2018-7-28 11:44
#include<iostream>
using namespace std;
int a[101],l[101],f[101],n;
void dfs(int x)
{
if(f[x]!=-1)dfs(f[x]);
cout<<a[x]<<' ';
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)cin>>a[i],l[i]=1,f[i]=-1;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
if(a[j]>=a[i]&&l[j]<l[i]+1)
{
l[j]=l[i]+1;
f[j]=i;
}
int k=1,t=1,maxa=-1;
while(t<=n)
{
if(l[t]>maxa)maxa=l[t],k=t;
t++;
}
dfs(k);
return 0;
}
复制代码
作者:
zhwang
时间:
2018-7-29 21:47
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[10001];
int f[10001];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
f[1]=1;
for(int i=1;i<=n;i++)
{
for(int j=i-1;j>=1;j--)
{
if(a[j]<=a[i])
{
f[i]=f[j]+1;
break;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
ans=max(ans,f[i]);
}
printf("%d",ans);
return 0;
}
复制代码
作者:
黄煦喆
时间:
2018-8-2 22:21
#include<iostream>
#include<algorithm>
using namespace std;
int n,len,l,r,mid;
int a[101],b[101];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
b[1]=a[1];
len=1;
for(int i=2;i<=n;i++)
if(a[i]>=b[len])b[++len]=a[i];
else
{
int k=upper_bound(b+1,b+len+1,a[i])-b;
b[k]=a[i];
}
cout<<len<<endl;
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2