最长单调子序列

简单来说:n个老鼠的体重和速度,求找出一个最长的子序列,这个子序列随着体重递增伴随速度递减,还要输出标号老鼠。
动态规划思路:dp[i] = max(dp[j])基础DP问题最长上升子序列的升级版,按照重量递减排序后算最长速度下降的长度的做法。难点在于如何输出老鼠们的编号,也就是记录路径,每只老鼠充当序列最大速度时对应的情况下长度是不一样的,存在一个递减顺序。
超级重点:dp数组保留了每种情况的最优解,因为动态方程是通过最优解递推得到下一个最优解,就拿样例来说,答案是4号老鼠开始的序列长度最大,每次增加一个长度,标号都放在了dp数组中。
#include< iostream>
#include< cstdio>
#include< cmath>
#include< algorithm>
using namespace std;
struct mice
{
int weight;
int number;
int speed;
}m[1010];
int cmp(mice a,mice b)
{
if(a.weight==b.weight)//同重量就比较速度
return a.speed>b.speed;
else return a.weight<b.weight;
}
int main()
{
int weight,speed,j=0;
while(scanf("%d %d",&weight,&speed)!=EOF)
{
m[j].weight=weight;
m[j].speed=speed;
m[j].number=j+1;
j++;
}
sort(m,m+j,cmp);//按照重量递增排序,同重量就按照速度大到小排列
int ma=0,num,dp[1010];
for(int i=0;i<j;i++)dp[i]=1;//每只老鼠都做最大值,所以初始长度为一。
for(int i=j-1;i>=0;i–)//这个是倒着来的,你也可以改掉正着来
{
for(int k=i+1;k<j;k++)
{
if(m[k].weight>m[i].weight&&m[k].speed<m[i].speed)
{
dp[i]=max(dp[k]+1,dp[i]);//动态方程
if(dp[i]>ma) ma=dp[i];//更新最大的长度也可以用ma=max(dp[i],ma)
}
}
}
cout<<ma<<endl;
int temp=ma;
for(int i=0;i<j;i++)//每个长度单位输出相应的标号。
{
if(dp[i]==temp)
{
cout<<m[i].number<<endl;
temp–;
}
if(!temp)break;
}
return 0;
}

发布了23 篇原创文章 · 获赞 0 · 访问量 336

猜你喜欢

转载自blog.csdn.net/qq_45762392/article/details/105107590