题目大意:输入数据直到文件结束,每行两个数据 体重M 和 速度V,将其排列得到一个序列,要求为:体重越大 速度越低(相等则不符合条件)。求这种序列最长的长度,并输出路径。答案不唯一,输出任意一种就好了。
题目思路:这是个最长上升子序列的问题,我们按W的升序进行排序,若W相等则按V的降序排序。用Pre[]记录当前点的前驱节点,Last记录序列最后一个点,maxn记录最长长度,完成动规后可根据Last和Pre[]输出路径。
#include<cstdio> #include<stdio.h> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> #define INF 0x3f3f3f3f #define MAX 1000005 using namespace std; int dp[MAX],pre[MAX],ans[MAX];//pre[]数组记录当前点的前驱节点 struct node { int w,v,id;//为防止排序后老鼠的编号丢失,所以用id记录下来 }a[MAX]; bool cmp(node A,node B) { if(A.w!=B.w) return A.w<B.w;//按体重升序排列 return A.v>B.v;//若体重相同则按速度降序排列 } int main() { int n,i,j,cnt=1,maxn=1,last=1; while(scanf("%d%d",&a[cnt].w,&a[cnt].v)!=EOF) { a[cnt].id=cnt; cnt++; } sort(a+1,a+cnt,cmp); for(i=1; i<MAX; i++) pre[i]=i;//初始化每个点的前驱节点为自己 for(i=0; i<MAX; i++) dp[i]=1;//最短的序列只包含自己,长度为一 for(i=1; i<cnt; i++) { for(j=1; j<=i; j++) { if(a[i].w>a[j].w && a[i].v<a[j].v) { if(dp[i] < dp[j]+1) { dp[i]=dp[j]+1; pre[a[i].id]=a[j].id;//记录当前点的前驱节点 } } if(maxn < dp[i]) { last=a[i].id;//更新最后一个节点 maxn=dp[i]; } } } printf("%d\n",maxn); for(i=maxn;i>=1;i--) { ans[i]=last; last=pre[last]; }//将pre[]倒着记录到ans[]里面 for(i=1;i<=maxn;i++) printf("%d\n",ans[i]); return 0; }
HDU 1160 FatMouse's Speed 动态规划 记录路径的最长上升子序列变形
时间: 2024-10-26 10:14:31