题目:
求最长的重量上升且iq下降的子序列
分析:
其实就是最长上升子序列的变形,其实很简单,先按重量按照由小到大进行排序,
然后就是LIS的事,打印路径的话,用数组path[]记录后面的位置,利用
递归实现打印(具体参考算法导论)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define X 1005
int dp[X],path[X];
struct node
{
int iq,w,id; //记录iq,重量以及未排序前的位置
}p[X];
int cmp(struct node a,struct node b)//按重量的非降序排列
{
return a.w<b.w;
}
void print(int id) //递归打印路径
{
cout<<p[id].id<<endl; //因为我是用数组记录后面的位置,所以先打印前面的id
if(path[id]!=-1)
print(path[id]); //递归实现打印后面的位置
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int cnt = 0;
while(scanf("%d%d",&p[cnt].w,&p[cnt].iq)!=EOF)
{
dp[cnt] = 1; //初始化dp
p[cnt].id = cnt+1; //记录id
cnt++;
}
sort(p,p+cnt,cmp);//对结构体进行排序
int ans = 0;
memset(path,-1,sizeof(path));
for(int i=cnt-1;i>=0;i--)
for(int j=i+1;j<cnt;j++)
if(p[i].iq>p[j].iq&&p[i].w<p[j].w) //如果重量小于后面的并且iq大于后面的
if(dp[i]<dp[j]+1)
{
path[i] = j; //记录路径
dp[i] = dp[j]+1;
}
int id;
for(int i=0;i<cnt;i++)
if(ans<dp[i])
{
ans = dp[i];
id = i; //找出最早的id
}
cout<<ans<<endl;
print(id);
return 0;
}