杭电1009(FatMouse' Trade)

本文介绍了一道关于FatMouse如何通过最优策略交换猫粮获取JavaBeans的问题。通过贪心算法和排序来最大化JavaBeans的获取量,给出了详细的代码实现。

FatMouse' Trade

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


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
// 贪心,排序求最优解;
 1 #include<stdio.h>
 2 #include<algorithm> 
 3 using namespace std;
 4 struct d 
 5 {
 6     double m,n;
 7     double value;
 8 };
 9 
10 d sum[100000];
11 
12 bool cmp(d m,d n)
13 {
14     return m.value>n.value;
15 }
16 
17 int main()
18 {
19     int a,b;
20     while(~scanf("%d %d",&a,&b))
21     {
22         if(a==-1&&b==-1)
23         break;
24         int i;
25         double total=0,c=0;
26         for(i=0;i<b;i++)
27         {
28             scanf("%lf %lf",&sum[i].m,&sum[i].n);
29             sum[i].value=sum[i].m/sum[i].n;
30         }
31         
32         sort(sum,sum+b,cmp);
33         
34     /*    for(i=0;i<b;i++) //为什么注释掉的部分for循环结束后,不加if语句OJ就一直错,搞不懂;
35         {
36             a-=sum[i].n;
37             if(a>=0)
38             total+=sum[i].m;
39             else
40             break;
41         }*/
42         for(i=0;i<b;i++)
43         {
44             if(a>sum[i].n)
45             {
46                 total+=sum[i].m;
47                 a-=sum[i].n;
48             }
49             else
50             {
51                 c=1;
52                 total+=a*sum[i].value;
53             }
54             if(c!=0)
55             break;
56         }
57         /*if(a<0)
58         total+=(a+sum[i].n)*sum[i].value; 
59         */printf("%.3lf\n",total);
60     }
61     return 0;
62 }

 

 

转载于:https://www.cnblogs.com/soTired/p/4548849.html

<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)形成有效序列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值