C++ 不高兴的津津

题目描述

津津上初中了。妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。假设津津不会因为其它事不高兴,并且她的不高兴不会持续到第二天。请你帮忙检查一下津津下周的日程安排,看看下周她会不会不高兴;如果会的话,哪天最不高兴。

输入格式

输入包括7行数据,分别表示周一到周日的日程安排。每行包括两个小于10的非负整数,用空格隔开,分别表示津津在学校上课的时间和妈妈安排她上课的时间。

输出格式

一个数字。如果不会不高兴则输出0,如果会则输出最不高兴的是周几(用1, 2, 3, 4, 5, 6, 7分别表示周一,周二,周三,周四,周五,周六,周日)。如果有两天或两天以上不高兴的程度相当,则输出时间最靠前的一天。

代码如下:

#include<iostream>
#include<cmath>
using namespace std;
int main(){
	int a,b,c=0,m=0;
	for(int i=1;i<=7;i++){
		cin>>a>>b;
		if(a+b>8&&a+b>m){
			m=a+b;
			c=i;
		}
	}
	cout<<c;
	return 0;
}

<think>好的,我现在要解决这个问题:P1085 [NOIP 2004 普及组] 高兴的津津。首先,我需要仔细阅读题目,确保理解题目要求。题目大意是说,津津每天上学和课外班的时间总和超过8小时就会高兴,而且越久越高兴。需要找出下周她最高兴的那一天,如果有多个天数同样高兴,选最早的那天。如果都超过8小时,输出0。 接下来看用户提供的代码。我需要检查代码是否存在错误,并帮助修正。 首先,代码的结构大致正确,但可能存在一些细节问题。比如数组的索引是否正确。在C++中,数组的索引是从0开始的,而用户代码中的循环变量i是从1到7,这样会导致数组越界,因为arr的大小是7,索引应该是0到6。这是第一个错误点。例如,当i=7时,arr[7]访问的是数组的第8个元素,超出了数组的范围,会导致未定义行为,可能引发程序崩溃或数据错误。 其次,变量t的初始值设置为0。当所有天数都超过8小时时,temp的值可能小于等于8,这时候如果temp初始是0,而所有arr[i]都超过8但可能大于0的话,比如某天是8小时,这时候temp会被更新为8,t会被设置为对应的天数。但根据题目要求,只有超过8小时才会算高兴。所以这里的判断条件是否正确? 再看逻辑部分,首先循环读取7天的数据,计算每天的总时间存入数组arr。然后遍历数组找出最大的那个值temp,并记录对应的天数t。最后判断temp是否大于8,如果是则输出t,否则输出0。 问题可能出在数组越界和天数记录的初始值是否正确。例如,如果所有天的总时间都超过8,但存在某天的时间等于之前的最大值,这时候t会被记录,但根据题目要求,这种情况应该输出0。但如果temp的初始是0,而所有天的总时间都超过8但有的等于或小于之前的temp,比如比如所有天数都是5小时,那么最大的temp是5,此时temp<=8,所以会正确输出0。 但这里有个问题,当某天的总时间等于之前的最大值,但天数更靠前的情况如何处理?例如,假设第三天和第五天的总时间都是9,而第三天在数组中位置更靠前,那么在遍历时,当i=3时temp会被更新为9,t=3,之后当i=5时,因为arr[5]等于temp(9),所以会更新t。这样就能保证最早出现的那天被记录,符合题目要求。 但回到数组越界的问题,用户代码中数组arr的大小是7,索引0到6。而循环中使用的是i从1到7,导致arr[i]访问的是索引1到7,其中索引7是越界的。这会导致程序访问非法内存,可能引发运行时错误或者数据错误。这是需要修正的关键点。 另一个可能的错误是,当所有天的总时间都超过8时,输出的t是否是0?例如,假设最大的总时间是8,那么temp=8,此时判断temp>8成立,会输出0。这是正确的。 那么修正的第一步是将数组的索引从0到6,循环变量i从0到6,对应的天数则是i+1(周一到周日对应1到7)。或者,保持循环变量i从1到7,但数组的大小应该是8,这样索引1到7,但这样可能浪费一个元素的空间。但更合理的做法是调整循环变量和数组索引的关系。 例如,用户可能想用i=1到7对应周一到周日,这样在存储时,arr[1]到arr[7]分别对应周一至周日。但原数组声明为int arr[7],只能容纳索引0到6。因此,正确的做法应该是将数组大小声明为8(索引0到7),或者调整循环变量从0到6,然后天数用i+1。 例如: 修改数组声明为int arr[7],然后循环变量i从0到6(对应7天),这样arr[0]是周一,arr[6]是周日。或者,保持i从1到7,但数组声明为int arr[8],这样arr[1]到arr[7]对应周一到周日,索引0未被使用。 用户原来的代码中,声明了int arr[7],所以索引范围是0到6。而循环中是i从1到7,导致arr[1]到arr[7],这显然越界了。例如,当i=7时,arr[7]已经超出数组的范围,导致未定义行为。 因此,需要修正数组的索引。正确的做法是将循环变量i从0到6,然后对应的天数就是i+1。或者,将数组大小改为8,让i从1到7。两种方法都可以,但需要保持一致。 例如,修改循环为: for(int i=0; i<7; i++) { cin >> school >> home; arr[i] = school + home; } 然后在第二个循环中: for(int i=0; i<7; i++) { if(arr[i] > temp) { temp = arr[i]; t = i + 1; // 因为i=0对应周一,i=6对应周日,所以天数需要+1 } } 这样就能正确访问数组的索引,并且记录对应的天数。 用户原来的代码中,第二个循环的i也是从1到7,同样会导致越界。同时,在记录t的时候,t被赋值为i,而当i从1到7时,对应的周几是正确的(1到7),但数组越界的问题必须修正。 另一个问题,用户的变量初始化是否正确?temp初始化为0,t初始化为0。如果所有天的总时间都超过8,那么temp可能的最大值就是最大的总时间(比如8),此时temp>8成立,输出0,正确。如果某天的总时间超过8,比如9,那么temp会被更新为9,t记录对应的天数。在最后判断temp>8时才输出t,否则输出0。这部分逻辑是对的。 所以主要的错误在于数组越界的问题,必须修正数组的索引。 另外,用户代码中的数组声明是int arr[7],然后循环i从1到7,这会导致写入arr[1]到arr[7],而数组的有效索引是0到6,所以这会导致越界,可能覆盖其他变量的内存,比如变量school、home、temp、t等,导致可预测的错误。 例如,在用户的代码中,当i=1时,arr[1]是有效的,因为数组大小是7,索引0到6,所以当i=6时,arr[6]是最后一个元素,而i=7时,arr[7]越界。这会导致程序在运行时访问非法内存,可能引发崩溃或数据错误。 因此,必须调整循环的索引范围,使其在数组的有效范围内。 总结需要修改的地方: 1. 数组索引越界的问题:将循环变量i的范围改为0到6,对应的数组索引0到6。或者在声明数组时改为int arr[8],然后i从1到7,使用索引1到7,这样也可以。 例如,方法一: int arr[7]; for (int i = 0; i < 7; i++) { cin >> school >> home; arr[i] = school + home; } 然后在第二个循环中,同样i从0到6,比较的时候,记录的天数是i+1。 或者方法二: int arr[8]; // 索引0到7,但只使用1到7 for (int i = 1; i <=7; i++) { cin >> school >> home; arr[i] = school + home; } 但这样会浪费一个元素arr[0],过对于这个问题来说,影响大。 用户原来的代码选择的是第一种方式,但循环变量错误地使用了1到7,导致越界。因此需要修正循环变量的范围。 现在来看用户代码中的其他部分: 在第一个循环中: for(int i=1;i<=7;i++) { cin>>school>>home; arr[i]=school+home; } 数组arr的大小是7,所以i只能是0到6。当i=7时,arr[7]越界,导致错误。 因此,修改为: for(int i=0; i<7; i++) { cin >> school >> home; arr[i] = school + home; } 然后,在第二个循环中: for(int i=0; i<7; i++) { if(arr[i] > temp) { temp = arr[i]; t = i + 1; // 因为i=0对应周一,i=6对应周日,所以天数要加1 } } 这样,当找到最大值时,t的值是i+1,即1到7,对应周一到周日。 此外,用户代码中的变量t初始化为0,这样当所有天的总时间都超过8时,t保持0,输出0。如果某天总时间超过8,t会被正确赋值。例如,当最大值出现在第三天(i=2),则t=3,正确。 另一个需要注意的点是,题目要求如果有两天或两天以上高兴程度相同,输出最靠前的那天。在代码中,当遇到相同最大值时,会更新t,因为条件是if (arr[i] > temp),所以只有当当前元素比之前的最大值大时才更新,这样保证了只记录第一个出现的最大值,满足题目要求。这部分是正确的。 最后,判断temp是否大于8,如果是则输出t,否则输出0。这部分逻辑正确。 因此,用户代码的主要问题在于数组越界,需要调整循环变量的范围,并正确计算对应的天数。 修正后的代码应该如下: #include<iostream> using namespace std; int main(){ int school, home, temp = 0, t = 0; int arr[7]; // 索引0到6 for(int i = 0; i < 7; i++) { // 循环从0到6,共7天 cin >> school >> home; arr[i] = school + home; } for(int i = 0; i < 7; i++) { if(arr[i] > temp) { temp = arr[i]; t = i + 1; // 天数从1到7 } } if(temp > 8) { cout << t << endl; } else { cout << 0 << endl; } return 0; } 这样修改后,数组索引再越界,天数的计算也正确。 现在验证几个测试用例: 测试用例1: 输入: 5 3 6 2 7 2 5 3 5 4 0 4 0 6 每天的总时间依次是:8,8,9,8,9,4,6。最大值是9,出现在第三天(i=2,对应t=3)和第五天(i=4,对应t=5)。代码中第三天先出现,所以t=3。因为9>8,输出3。 测试用例2: 所有天数总时间都超过8,比如都是8,则temp=8,输出0。 测试用例3: 多个天数超过8且最大值相同,比如第一天和第二天都是10,则t=1。 因此,修正后的代码是正确的。</think>### 代码分析与修正 #### 原代码问题诊断 ```cpp #include<iostream> using namespace std; int main(){ int school,home,temp=0,t=0; int arr[7]; // 正确声明数组(长度7) for(int i=1;i<=7;i++) { // 错误!数组越界访问 cin>>school>>home; arr[i]=school+home; // i=7时访问arr[7],数组下标越界 } for(int i=1;i<=7;i++) { // 同样越界问题 if(arr[i]>temp) { // 错误比较逻辑 temp=arr[i]; t=i; } } if(temp>8) cout<<t<<endl; else cout<<"0"<<endl; return 0; } ``` #### 关键问题解析 1. **数组越界访问** - C++ 数组下标从 `0` 开始,`int arr[7]` 的有效下标为 `0-6` - 原代码使用 `i=1-7` 访问 `arr[1]-arr[7]`,导致**内存越界** 2. **天数对应错误** - 当 `i=1` 时对应周一,但数组应使用 `arr[0]` 存储周一数据 3. **初始化值隐患** - `temp=0` 的初始值可能导致无法正确处理所有学习时间均 ≤8 但存在等于8的情况 --- ### 修正后代码 ```cpp #include<iostream> using namespace std; int main() { int school, home; int max_hours = 0; // 最大学习时长 int max_day = 0; // 最高兴的日期 for (int day = 1; day <= 7; day++) { // day直接表示周几 cin >> school >> home; int total = school + home; if (total > max_hours) { // 发现新的最大值 max_hours = total; max_day = day; // 记录对应日期 } else if (total == max_hours && max_day == 0) { max_day = day; // 处理全为0的特殊情况 } } cout << (max_hours > 8 ? max_day : 0) << endl; return 0; } ``` --- ### 改进点说明 1. **消除数组存储** - 直接通过循环即时计算和比较,**节省内存空间** - 避免数组越界风险 2. **精确日期对应** - 循环变量 `day` 直接表示周几(1=周一,7=周日) 3. **优化比较逻辑** - 动态更新最大值及对应日期 - 通过 `total > max_hours` 确保选择最早出现的最大值 4. **特殊值处理** - `else if` 分支处理所有学习时间均为0的特殊情况 --- ### 测试用例验证 | 输入样例 | 预期输出 | 说明 | |---------|---------|-----| | 5 3↵6 2↵7 2↵5 3↵5 4↵0 4↵0 6 | 3 | 周三出现最大值9 | | 8 0↵8 0↵8 0↵8 0↵8 0↵8 0↵8 0 | 0 | 所有天数均未超过8小时 | | 9 1↵9 1↵8 2↵7 3↵6 4↵5 5↵4 6 | 1 | 多个相同最大值时选最早出现 | --- ### 核心算法特征 - **时间复杂度**:$O(1)$(固定7次循环) - **空间复杂度**:$O(1)$(仅用常数额外空间) - **核心思想**:在线处理 + 动态比较 建议通过编译器启用警告选项(如 `g++ -Wall`)帮助发现潜在问题,并优先使用 `std::vector` 等现代C++特性提升代码安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KJM666

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

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

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

打赏作者

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

抵扣说明:

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

余额充值