题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160
题目分析:输入一组体重和速度的数据,找到尽可能长的序列,满足体重严格递增,速度严格递减。
解题思路:先按体重升序排列,然后在排列后的数据中找到最长的递减的序列。这里由于不仅仅是要你输出序列的长度,还要输出最长的序列是由哪些数据组成。这样在DP的同时,需要记录每一个最优解得到的过程。
其实这个跟求最长递增序列是一样的思路。参考:http://blog.csdn.net/kay_zhyu/article/details/8713068
这里,用一个flag数组来记录,数据i之前的速度比i大的最长的点的编号。在最后打印的时候,需要翻转过来,按体重升序打印。
参考代码:
#include <stdio.h>
#include <stdlib.h>
#define M 1005
struct tu
{
int w;
int s;
int ID;
}a[M];
int dp[M];
int flag[M];
int temp[M];
int compare(const void *a, const void *b)
{
struct tu *t1 = (struct tu *)a;
struct tu *t2 = (struct tu *)b;
return t1->w - t2->w;
}
void main()
{
int n,i,j;
int nMax,r;
n= 0;
while(scanf("%d %d",&a[n].w,&a[n].s) != EOF)
{
a[n].ID = n + 1;
++n;
}
//按体重升序排列
qsort(a,n,sizeof(a[0]), compare);
nMax = 0;
for(i = 0; i < n; ++i)
{
dp[i] = 1;
flag[i] = -1;
for(j = 0; j < i; ++j)
{
if(a[j].s > a[i].s && dp[i] < dp[j] + 1)
{
dp[i] = dp[j] + 1;
flag[i] = j;//记下到i的最大的j的编号
}
}
if(dp[i] > nMax)
{
nMax = dp[i];
r = i;
}
}
printf("%d\n",nMax);
i = 0;
while(r >= 0)
{
temp[i++] = r;//用temp数组来辅助,把结果反转过来输出
r = flag[r];
}
for(; i > 0; --i)
{
printf("%d\n",a[temp[i - 1]].ID);
}
}