信息奥赛一本通1229:电池的寿命

【题目描述】
小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电。为了保证能够长时间玩游戏,他买了很多5号电池,这些电池的生产商不同,质量也有差异,因而使用寿命也有所不同,有的能使用5个小时,有的可能就只能使用3个小时。显然如果他只有两个电池一个能用5小时一个能用3小时,那么他只能玩3个小时的游戏,有一个电池剩下的电量无法使用,但是如果他有更多的电池,就可以更加充分地利用它们,比如他有三个电池分别能用3、3、5小时,他可以先使用两节能用3个小时的电池,使用半个小时后再把其中一个换成能使用5个小时的电池,两个半小时后再把剩下的一节电池换成刚才换下的电池(那个电池还能用2.5个小时),这样总共就可以使用5.5个小时,没有一点浪费。

现在已知电池的数量和电池能够使用的时间,请你找一种方案使得使用时间尽可能的长。

【输入】
输入包含多组数据。每组数据包括两行,第一行是一个整数N(2≤N≤1000),表示电池的数目,接下来一行是N个正整数表示电池能使用的时间。

【输出】
对每组数据输出一行,表示电池能使用的时间,保留到小数点后1位。

【输入样例】
2
3 5
3
3 3 5
【输出样例】
3.0
5.5

题解:
因为只有两节电池的话,能够玩游戏的时间就是其中短的那节电池的时间
当电池节数超过3节时,玩游戏的时间就是所有电池的时间和除以2
比如3 3 5时,先把第一节能用3小时的电池和第二节能用3小时的电池,放一起用,用0.5小时后,再把第二节电池拿掉,把能用5小时的电池换上,用2.5小时候,第一节电池电量用完,再换上第二节电池,还能用2.5小时,没有任何浪费。 玩游戏时间为5.5小时。
比如3 4 5时,先把第一节能用3小时的电池和第二节能用4小时的电池,放一起用,用1小时后,再把第二节电池拿掉,把能用5小时的电池换上,用2小时候,第一节电池电量用完,再换上第二节电池,还能用3小时,没有任何浪费。玩游戏时间为6小时。
比如3 4 5 6时,先把能用3和6的两节电池放一起用,用3小时后,一节电池电量耗光,另一节电池还能用3小时,还有两节电池能用4,5小时,这时候回到了3 4 5 这个问题上,所以总的玩游戏时间为9小时。

//1229:电池的寿命
#include<iostream>
#include<iomanip>
using namespace std;
int n,a[1001],sum=0,i,j;
double ave;
int main()
{

    while(cin>>n)
    {
    	sum=0;
		for(i=1;i<=n;i++)
    	{
		cin>>a[i];
		sum+=a[i];
		}
    if(n==2)//因为只有两节电池的话,能够玩游戏的时间就是其中短的那节电池的时间 
    {
    	ave=a[1]>a[2]?a[2]:a[1];
    	cout<<fixed<<setprecision(1)<<ave<<endl;
	}
	else
	{
		ave=sum*1.0/2;
		cout<<fixed<<setprecision(1)<<ave<<endl;	
	}
    }
    
	
	return 0;
}

<think>我们正在解决信息奥赛一本中的题目:删除单词后缀(题目编号1141)。 题目要求:给定一个单词,如果单词以"er"、"ly"或"ing"结尾,则删除这个后缀(只删除一个后缀,且题目保证删除后单词长度不为0)。 注意:后缀的删除优先级是,如果有多个后缀同时满足,优先删除最长的后缀(即先检查3字符的后缀"ing",再检查2字符的后缀"er"和"ly")。 解题思路: 1. 读取输入的单词。 2. 获取单词长度。 3. 按照优先级检查后缀(先检查3字符的"ing",再检查2字符的"er"和"ly"): - 如果单词长度大于等于3且最后三个字符是"ing",则删除这三个字符(即新字符串长度为原长度减3)。 - 否则,如果单词长度大于等于2且最后两个字符是"er",则删除这两个字符。 - 否则,如果单词长度大于等于2且最后两个字符是"ly",则删除这两个字符。 4. 输出处理后的字符串。 注意:题目只要求删除一个后缀,所以一旦匹配到一个后缀并删除,就不再检查其他后缀。 代码实现(C++):</think># 信息奥赛一本 1141:删除单词后缀 解题方法 ## 题目分析 题目要求删除单词的特定后缀(`er`、`ly` 或 `ing`),但只删除一个后缀。关键点在于: 1. **后缀优先级**:优先删除最长的后缀(`ing` > `er`/`ly`) 2. **后缀长度**:`ing` 是3字符后缀,`er` 和 `ly` 是2字符后缀 3. **边界条件**:删除后单词长度不为零 ## 高效解题思路 ### 算法步骤 1. **获取单词长度**:确定字符串长度 `len` 2. **检查后缀优先级**: - 先检查3字符后缀 `ing`(最长后缀优先) - 再检查2字符后缀 `er` - 最后检查2字符后缀 `ly` 3. **调整长度**:匹配到后缀则减少对应长度 4. **输出结果**:截取原始字符串的前 `len` 个字符 ### 时间复杂度 $O(1)$,所有操作都是常数时间操作(后缀检查使用子串截取,最大检查长度固定为3) ## C++ 代码实现 ```cpp #include <iostream> #include <string> using namespace std; int main() { string s; cin >> s; // 读取输入单词 int len = s.size(); // 获取原始长度 // 优先检查并删除最长后缀 "ing"(3字符) if (len >= 3 && s.substr(len-3, 3) == "ing") { len -= 3; // 长度减少3 } // 检查并删除 "er"(2字符) else if (len >= 2 && s.substr(len-2, 2) == "er") { len -= 2; // 长度减少2 } // 检查并删除 "ly"(2字符) else if (len >= 2 && s.substr(len-2, 2) == "ly") { len -= 2; // 长度减少2 } cout << s.substr(0, len) << endl; // 输出处理后的单词 return 0; } ``` ## 关键点解析 1. **后缀检查顺序**:必须按照 `ing` → `er` → `ly` 的顺序检查,确保优先删除最长后缀 2. **边界保护**:每次检查前验证字符串长度(`len >= 2` 或 `len >= 3`)避免越界 3. **子串截取**:使用 `substr(pos, len)` 方法: - `s.substr(len-3, 3)` 获取最后3个字符 - `s.substr(0, len)` 输出处理后的单词 4. **长度调整**:匹配到后缀时修改长度变量 `len`,最后统一截取 ## 测试用例验证 | 输入 | 输出 | 说明 | |---------------|------------|--------------------------| | `referer` | `refer` | 删除 `er` 后缀 | | `friendly` | `friend` | 删除 `ly` 后缀 | | `jumping` | `jump` | 删除 `ing` 后缀 | | `ingly` | `ly` | 只删除一个后缀(`ing`) | | `hello` | `hello` | 无匹配后缀 | | `sing` | `s` | 删除 `ing` 后缀 | ## 算法优化 对于性能要求更高的场景,可避免使用 `substr`,直接比较最后几个字符: ```cpp // 优化版本(避免substr开销) if (len >= 3 && s[len-3]=='i' && s[len-2]=='n' && s[len-1]=='g') { len -= 3; } else if (len >= 2 && s[len-2]=='e' && s[len-1]=='r') { len -= 2; } else if (len >= 2 && s[len-2]=='l' && s[len-1]=='y') { len -= 2; } ``` ## 常见错误规避 1. **顺序错误**:若先检查 `er` 再检查 `inger`,会导致错误删除部分后缀 2. **长度检查缺失**:未检查 `len >= 3` 直接取最后3字符会导致运行时错误 3. **多次删除**:题目要求只删除一个后缀,无需循环处理 > 本题考察字符串基础操作和条件判断逻辑,是信息奥赛中典型的字符串处理入门题[^1]。 [^1]:信息奥赛一本》字符串处理专题解析,详见 [ybt 题解精要](https://oi-wiki.org/string/)。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mengdicfm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值