题目链接:Click here
题意:给出一些老鼠的重量和奔跑速度,要求给出一个最长的排列,其中,前一只老鼠的重量严格小于后一只老鼠,而它的速度要严格大于后一只老鼠。给出的排列可能与示例不同,因为排列可能有多种,只要求出一种就可以了。
思路:乍一看,重量从小到大,同时速度从大到小,双向的最长上升或下降子序列,其实可以将重量从大到小排序,这样的话就变成速度的最大上升子序列问题。这道题还要求记录子序列的标号,所以有点麻烦~~
具体思路看代码吧:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int w, s;
int index; //储存标号,因为要排序,怕标号混乱
} mouse[1005]; //小鼠的信息
bool cmp(node a, node b)
{
if(a.w == b.w) //先体重,后速度
return a.s < b.s;
return a.w < b.w;
}
int main()
{
int dp[1005], load[1005], ans[1005];
int i, maxl, maxi, n, temp, x;
i = 1;
while(scanf("%d%d", &mouse[i].w, &mouse[i].s) != EOF)
{
mouse[i].index = i;
dp[i] = 1;
load[i] = 0;
i++;
}
sort(mouse + 1, mouse + i, cmp);
n = i - 1;
maxl = 0;
for(i = 2; i <= n; i++)
{
for(int j = 1; j < i; j++)
if(mouse[i].w > mouse[j].w && mouse[i].s < mouse[j].s && dp[i] < dp[j] + 1)
{
//如果i的体重比j的小,而且速度j的大,并且还得j的最长子序列加一要大于目前i的最长子序列
dp[i] = dp[j] + 1;
load[i] = j;
}
if(dp[i] > maxl)
{
//如果目前最长子序列大于了最终的子序列长度,则替换。
maxl = dp[i];
maxi = i;
}
}
temp = maxi;
x = 0;
while(temp != 0)
{//将最终的结果标号存入数组中
ans[x] = temp;
temp = load[temp];
x++;
}
printf("%d\n", maxl);
for(i = maxl - 1; i >= 0; i--)//标号存的时候是倒序,所以要给它反过来
printf("%d\n", mouse[ans[i]].index);
return 0;
}