最简单的DP。。。并且在被提示了考虑dp[i]为i结尾的子序列的最长子序列,各种姿势还是没做出来。。
把体重降序排列,就变成了求速度的最长上升子序列,输出正是按次要求,也不用再倒序;
n<1000
n^2复杂度足以;但是LIS有nlogn的算法:点击打开链接
/* *********************************************** Author :angon ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <stack> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; #define REP(i,k,n) for(int i=k;i<n;i++) #define REPP(i,k,n) for(int i=k;i<=n;i++) #define scan(d) scanf("%d",&d) #define scann(n,m) scanf("%d%d",&n,&m) #define LL long long #define maxn 1005 #define mod 100000007 int dp[maxn],pre[maxn]; struct node { int w,s; int id; }t[maxn]; bool cmp(node n1,node n2) { return n1.w>n2.w || (n1.w==n2.w && n1.s<n2.s); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n=1,edx; while(~scanf("%d%d",&t[n].w,&t[n].s)) { t[n].id=n; pre[n]=0; dp[n]=1; n++; // if(n==10) break; } sort(t+1,t+n,cmp);//对体重降序排列,求速度的最长上升子序列 int maxlen=-1; REP(i,1,n) { REP(j,1,i) { if(t[i].w < t[j].w && t[i].s > t[j].s && dp[i]<dp[j]+1) //如果dp[i]>dp[j]就没必要再管 { dp[i]=dp[j]+1; pre[i]=j; if(dp[i]>maxlen) { maxlen=dp[i]; edx=i; } } } } printf("%d\n",maxlen); REP(i,0,maxlen) { printf("%d\n",t[edx].id); edx=pre[edx]; } return 0; }
#include <iostream> using namespace std; int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n { int left=0,right=len,mid=(left+right)/2; while(left<=right) { if(n>a[mid]) left=mid+1; else if(n<a[mid]) right=mid-1; else return mid; mid=(left+right)/2; } return left; } int main(void) { int n,a[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标 while(cin>>n) { for(i=0;i<n;i++) cin>>a[i]; b[0]=1; c[0]=-1; c[1]=a[0]; len=1;//此时只有c[1]求出来,最长递增子序列的长度为1. for(i=1;i<n;i++) { j=find(c,len,a[i]); c[j]=a[i]; if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1 len=j;//更新len } cout<<len<<endl; } return 0; }