FatMouse's Speed HDU - 1160 (最长上升子序列)

本文探讨了如何从一组老鼠的数据中寻找最长子序列的问题,该子序列要求老鼠的体重递增而速度递减。通过使用C++实现算法,文章提供了一个具体的样例输入与输出,展示了如何有效地解决这个问题。

很多肥老鼠认为,长的越肥,奔跑速度就越快,为了反驳这个观点,你现在需要对老鼠的体重和速度进行研究,你要在老鼠序列中找出一个子序列,使得老鼠的体重在增加,但是速度却在减慢Input
输入以eof结束。
输入中每行有两个正整数,分别表示老鼠的体重和速度,范围均在1到10000之间,输入数据最多有1000只老鼠。
某些老鼠可能有相同的体重,某些老鼠可能有相同的速度,某些老鼠可能体重和速度都相同。
Output
 
我们是要在原来的老鼠序列中,找到一个最长的子序列,使得这个子序列中老鼠的体重在严格增加,速度却在严格降低。
首先输出满足条件的最长的子序列的长度。
其次,输出一个最长子序列的方案,要求输出每个老鼠在输入时候的编号,每个编号占一行,任意一种正确的方法都会被判正确。
Sample Input
6008 1300
6000 2100
500 2000
1000 4000
1100 3000
6000 2000
8000 1400
6000 1200
2000 1900 
Sample Output
 
4
4
5
9
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
struct node
{
    int x,y,id;
}e[1100];
int dp[1100];
int mark[1100];
int cmp(node n1,node n2)
{
    if(n1.y==n2.y)
       return n1.x>n2.x;
   return n1.y>n2.y;
}
int main()
{
    int n=1;
    while(~scanf("%d%d",&e[n].x,&e[n].y))
    {
        e[n].id=n;
        n++;
    }
    sort(e+1,e+1+n,cmp);
    memset(dp,inf,sizeof(dp));
    int k=0;
    for(int i=1;i<n;i++)
    {
        int j=lower_bound(dp+1,dp+1+n,e[i].x)-dp;
        dp[j]=e[i].x;
        mark[i]=j;
        k=max(k,j);
    }
    printf("%d\n",k);
    int ans[1100];
    int u=0;
    for(int i=n-1;i>=1;i--)
    {
        if(mark[i]==k)
        {
            ans[u++]=e[i].id;
            k--;
        }
    }
    for(int i=u-1;i>=0;i--)
        printf("%d\n",ans[i]);
}



<think>嗯,用户想了解FatMouse's Speed这个算法题的解法,可能是在准备竞赛或者学习动态规划。首先,我需要回忆一下这个题目的内容。根据引用3提到的,这是一个简单的DP问题,测试数据较松,O()算法也能过。题目应该是要求找出最的子序列,满足老鼠体重递增而速度递减。 接下来,我需要确定问题具体要求。比如输入是多个老鼠体重速度,要求找出最的序列,其中每只老鼠比前一只更重但更慢。同时可能需要输出这个子序列的顺序。这递增子序列(LIS)问题类似,但有两个条件需要考虑。 然后,思考如何建模。通常处理这类问题的方法是先排序,将其中一个条件固定,转化为另一个条件的最序列。例如,按体重递增排序,如果体重相同则按速度递减,这样问题转化为在速度中找最递减子序列,但必须保证原序列中的体重严格递增。不过,可能存在相同体重的情况,这时候需要处理。例如,排序时应确保相同体重老鼠速度降序排列,这样在后续处理时,相同体重的不会干扰,因为后面的速度更小的话也无法满足体重递增的条件。 接下来是动态规划的思路。每个位置i的最子序列度可以由前面所有j<i且满足体重严格小于i且速度严格大于i的位置j的最大值加1。这样时间复杂度是O(),而题目中n最多是1000,所以应该是可行的。 然后考虑如何记录路径,以便最后输出选中的老鼠的顺序。这通常需要维护一个pre数组,记录每个位置的前驱节点,最后从最大度的位置回溯。 另外,需要注意输入输出的格式。输入每行两个整数,可能有多组数据,直到文件结束。输出应该是最子序列的度,以及按顺序的老鼠编号(可能按原始输入的顺序,所以排序前需要记录原始位置)。 现在,验证这些思路是否正确。例如,排序是否正确处理了体重相同的情况。如果两只老鼠体重相同,即使速度不同,也不能出现在同一个序列中,因为体重必须严格递增。因此,在排序时,应该将体重相同的按速度降序排列,这样在处理时,后面的老鼠速度更小,但体重相同,不会被选中,从而避免错误。 然后,动态规划的状态转移是否正确。每个元素dp[i]表示以第i只老鼠结尾的最子序列度。状态转移需要遍历前面所有符合条件的元素,并取最大值加1。 路径记录的实现需要仔细处理。每个位置i的pre[i]存储前一个的位置,这样最后找到最子序列的末尾后,可以逆序回溯得到正确的顺序。 另外,初始情况下,每个dp[i]至少是1,即自身构成一个子序列。然后逐步更新。 最后,代码的结构大致是先读取所有数据,记录原始索引,然后排序,接着进行动态规划,同时记录路径,最后找到最子序列,并逆序输出。 可能的问题点包括:排序是否合理,如何处理体重相同的情况,动态规划条件是否正确,路径记录是否正确,以及输出时的顺序是否正确。例如,在排序后,原始索引可能需要保存,以便输出时使用原始的顺序编号。 测试用例方面,比如输入几个老鼠的数据,验证是否得到正确的最子序列。例如,输入三只老鼠(体重速度)分别为(6008, 1300), (6000, 2100), (500, 2000)。排序后按体重递增,所以顺序是500,6000,6008。对应的速度是2000,2100,1300。此时最子序列是500→6000→6008,对应的速度是2000→2100→1300,但因为速度需要递减,所以中间这个不符合,所以正确的最子序列应该是500→6008,度为2。或者可能需要更详细的测试。这说明在动态规划时需要严格检查体重速度的条件。 综上,正确的解法应该是排序后应用动态规划,注意处理相同体重的情况,并且正确记录路径。</think>### FatMouse's Speed 算法题解 #### 问题描述 给定一组老鼠体重速度数据,要求找到**最的子序列**,满足以下条件: 1. 体重严格递增 2. 速度严格递减 3. 输出子序列度及具体老鼠的原始输入顺序编号 #### 解题思路 1. **预处理与排序** 将老鼠体重升序排序,若体重相同则按速度降序排序。这一步固定体重顺序,将问题简化为**在速度序列中寻找最递减子序列**。 2. **动态规划建模** - 定义 $dp[i]$ 表示以第 $i$ 只老鼠结尾的最子序列- 状态转移方程: $$dp[i] = \max_{\substack{j < i \\ \text{speed}[j] > \text{speed}[i]}} (dp[j] + 1)$$ - 同时记录路径 $pre[i]$ 表示前驱节点 3. **路径回溯** 通过 $pre$ 数组从最子序列末尾回溯到起始位置,最终逆序输出原始编号。 #### 代码实现 ```python mice = [] index = 1 while True: try: w, s = map(int, input().split()) mice.append((w, s, index)) # (weight, speed, original_index) index += 1 except EOFError: break # 排序:体重升序,速度降序 mice.sort(key=lambda x: (x[0], -x[1])) n = len(mice) dp = [1] * n pre = [-1] * n max_len = 1 end_pos = 0 for i in range(n): for j in range(i): if mice[j][0] < mice[i][0] and mice[j][1] > mice[i][1] and dp[j] + 1 > dp[i]: dp[i] = dp[j] + 1 pre[i] = j if dp[i] > max_len: max_len = dp[i] end_pos = i # 路径回溯 path = [] while end_pos != -1: path.append(mice[end_pos][2]) end_pos = pre[end_pos] print(max_len) for num in reversed(path): print(num) ``` #### 关键分析 1. **时间复杂度** 动态规划部分为 $O(n^2)$,适用于 $n \leq 1000$ 的数据规模[^3] 2. **排序技巧** 通过将体重相同的元素按速度降序排列,确保后续处理时不会选择到体重相同的元素 3. **路径记录** 通过 $pre$ 数组实现路径回溯,需注意最终输出顺序要逆序 #### 典型测试用例 输入: ``` 6008 1300 6000 2100 500 2000 ``` 输出: ``` 2 3 1 ``` 说明:选择第3只(500g/2000cm/s)第1只(6008g/1300cm/s)形成有效序列
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值