杭电-1009 FatMouse' Trade

此问题探讨了FatMouse如何通过最优交换策略,利用有限的猫粮换取仓库中最大数量的JavaBeans。涉及多个房间的不同交换比例,需找出最大收益。

FatMouse' Trade

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 66325    Accepted Submission(s): 22518


Problem Description
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
 

Input
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1's. All integers are not greater than 1000.
 

Output
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
 

Sample Input
  
5 3 7 2 4 3 5 2 20 3 25 18 24 15 15 10 -1 -1
 

Sample Output
  
13.333 31.500
 

Author
CHEN, Yue
 

Source
 

Recommend
JGShining
 

AC代码:

<pre name="code" class="cpp">#include <stdio.h>
#include <algorithm>
using namespace std;

struct Node
{
    double j,f,p;
} node[10000];

int cmp(Node x,Node y)
{
    return x.p>y.p;
}

int main()
{
    int m,n;
    while(~scanf("%d%d",&n,&m) && (m!=-1 || n!=-1))
    {
        double sum = 0,max = 0;
        int i,j;
        for(i = 0; i<m; i++)
        {
            scanf("%lf%lf",&node[i].j,&node[i].f);
            node[i].p = node[i].j/node[i].f;
        }
        sort(node,node+m,cmp);
        for(i = 0; i<m; i++)
        {
            if(n>=node[i].f)
            {
                sum+=node[i].j;
                n-=node[i].f;
            }
            else
            {
                sum+=node[i].p*n;
                break;
            }
        }
        printf("%.3lf\n",sum);
    }

    return 0;
}




                
(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
<think>嗯,用户想了解FatMouse's Speed这个算法题的解法,可能是在准备竞赛或者学习动态规划。首先,我需要回忆一下这个题目的内容。根据引用3提到的,这是一个简单的DP问题,测试数据较松,O(n²)算法也能过。题目应该是要求找出最长的子序列,满足老鼠的体重递增而速度递减。 接下来,我需要确定问题具体要求。比如输入是多个老鼠的体重和速度,要求找出最长的序列,其中每只老鼠比前一只更重但更慢。同时可能需要输出这个子序列的顺序。这和最长递增子序列(LIS)问题类似,但有两个条件需要考虑。 然后,思考如何建模。通常处理这类问题的方法是先排序,将其中一个条件固定,转化为另一个条件的最长序列。例如,按体重递增排序,如果体重相同则按速度递减,这样问题转化为在速度中找最长递减子序列,但必须保证原序列中的体重严格递增。不过,可能存在相同体重的情况,这时候需要处理。例如,排序时应确保相同体重的老鼠按速度降序排列,这样在后续处理时,相同体重的不会干扰,因为后面的速度更小的话也无法满足体重递增的条件。 接下来是动态规划的思路。每个位置i的最长子序列长度可以由前面所有j<i且满足体重严格小于i且速度严格大于i的位置j的最大值加1。这样时间复杂度是O(n²),而题目中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)形成有效序列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值