起因:
在洛谷偶然刷到了这道题
一看,嘶,边界条件有点多啊,先试试吧~
第一次的思路:
先对总天数进行除以 7 的操作,得到星期数
然后再对总天数进行对 7 取余的操作,得到剩余的天数
星期数乘以 5 再加上剩余的天数就是实际游的天数
最后加上特殊边界的判断:
如果开始的时间是星期六,则将总天数减去两天
如果开始的天数是星期天,则将总天数减去一天
最后拿实际天数乘以 250 就是总里程了~
perfect!似乎思路没有问题,但是直觉告诉我并没有这么简单~
第一次的源码:
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int start, day;
cin >> start >> day;
int week = day / 7;
int remain = day % 7;
int real_day = week * (7-2) + remain;
if (start == 6)
real_day -= 2;
else if (start == 7)
real_day -= 1;
int distance = real_day * 250;
cout << distance << endl;
return 0;
}
第一次的结果:
emmmmmm,想了半天没想出来我的思路有什么问题,下个测试点看看~
这是测试点2的数据
97061250 / 250 = 388,245,所以实际的天数应该是388245天
演算一下我代码的结果:
可以看到 real_day 的结果是没有错误的,但是因为开始的日期是星期天,所以结果少了一天的里程
思考了一下,难道说开始日期是星期六或者星期天也需要继续游吗?
于是我照着这个思路改了一下代码:
第二次的思路:
先对总天数进行除以 7 的操作,得到星期数
然后再对总天数进行对 7 取余的操作,得到剩余的天数
星期数乘以 5 再加上剩余的天数就是实际游的天数
与第一次不同的是不对特殊情况做判断
最后拿实际天数乘以 250 就是总里程了~
第二次的源码:
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int start, day;
cin >> start >> day;
int week = day / 7;
int remain = day % 7;
int real_day = week * (7-2) + remain;
int distance = real_day * 250;
cout << distance << endl;
return 0;
}
第二次的结果:
可以看到这个思路并不是正确的,于是我又下了一个测试点~
这是测试点3的数据:
1750 / 250 = 7,10天不满两周,实际天数应该是8天,再减去开始游的当天,实际天数就是7天,也就是说如果开始天数是在星期六或者星期天的话,也是不需要游泳的(这条鱼还真是会偷懒...........)
这时候我突然灵光一闪(也可能是脑子一抽),如果week的天数刚好能被 7 整除,那么remain的天数就是 0,这时候无论是从哪天开始,都是经历了完整的 n 周,实际天数应该不会再受到星期六和星期天的影响,实际天数应为 n * (7-5)
于是我照着这个思路开始改代码
第三次的思路:
先对总天数进行除以 7 的操作,得到星期数
然后再对总天数进行对 7 取余的操作,得到剩余的天数
星期数乘以 5 再加上剩余的天数
如果remain为0,则表示经历了完整的n周,此时不进行特殊判断
如果remain不为0,则表示经历了不完整的n周,此时加上边界判断
加上特殊边界的判断(判断remain是否为0):
如果开始的时间是星期六且remain不为0,则将总天数减去两天
如果开始的天数是星期天且remain不为0,则将总天数减去一天
最后拿实际天数乘以 250 就是总里程了~
第三次的源码:
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int start, day;
cin >> start >> day;
int week = day / 7;
int remain = day % 7;
int real_day = week * (7-2) + remain;
if (remain != 0)
{
if (start == 6)
real_day -= 2;
else if (start == 7)
real_day -= 1;
}
int distance = real_day * 250;
cout << distance << endl;
return 0;
}
第三次的结果:
纳尼? 还有什么条件我没判断到?
开始有点怀疑人生了 T^T
于是不信邪的我,下载了最后一个没过的测试点(当天下载测试点的机会用完了,这条测试点是我几天后才下的~)
这是八个测试点:
2204250 / 250 = 8817
演算一下我代码的结果:
也就是说多算了两天的路程~
嘶~
这时候看了看这个开始日期,emmmmm,星期四,还是我的幸运日,嘿嘿~
再看看余数,四天,也就是说停止游泳的日期是星期一,中间刚好有两天的休息日期,会不会就是这两天多算了?
这样想,如果开始的日期不是星期六或者星期天,不是整数周,但是最后一周的时候经过了星期六或者星期天这两天,那么也应该是要休息的,所以第三种方法的特殊情况判断是有问题的
第四次的思路:
先对总天数进行除以 7 的操作,得到星期数
然后再对总天数进行对 7 取余的操作,得到剩余的天数
星期数乘以 5 再加上剩余的天数
如果remain为0,则表示经历了完整的n周,此时不进行特殊判断
如果remain不为0,则表示经历了不完整的n周,此时加上边界判断
加上特殊边界的判断(判断remain是否为0):
1.如果开始的星期数加上剩余的天数等于7或者开始的日期也是星期天
则将实际天数减去1
(比如说开始的天数是星期四,remain是3,那么 要经历星期四,星期
五,星期六,休息一天,如果remain是4,那么要经历星期四,星期
五,星期六,星期天,休息两天,此时跳转到第二种情况)
(如果开始的日期是星期天,如果remain是1,则会当天休息一天,由
于取余,所以余数不会超过6,所以其他情况下游泳时间最多持续到下
周五,实际休息时间就是一天)
(如果开始的日期是星期六,如果reamain超过了两天则会跳转到第二
种情况,实际休息两天,如果只有一天,则当天休息实际休息一天 )
(what's up,逻辑确实绕~,在复盘的时候差点把我cpu干爆了)
2.如果开始的星期数加上剩余的天数大于8了,则表示经过了完整的一
周,自然有两天的休息日,所以实际天数要减去2
最后拿实际天数乘以 250 就是总里程了~
第四次的源码:
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int start, day;
cin >> start >> day; // 输入开始游泳的周数和经过的天数
int week = day / 7; // 计算完整的周数
int remain = day % 7; // 计算剩余的天数
int real_day = week * (7-2) + remain; // 计算实际游泳的天数
if (remain != 0) // 如果remain不为0,需要考虑剩余天数对周数的影响
{
if (start + remain == 7 || start == 7 )
real_day -= 1; // 如果剩余天数为0或1,则减少1天
else if (start + remain >= 8)
real_day -= 2; // 如果剩余天数大于等于2,则减少2天
}
long long distance = real_day * 250; // 计算累计游泳的距离
cout << distance << endl; // 输出结果
return 0;
}
第四次的结果:
此时我的大脑内不由唱起那首歌,喂 ~俺个炊饼~马飞诶~
太不容易了,这玩意设置为入门难度简直就是在骗人~
参考了一下其他大佬的解法,发现这玩意其实可以用循环来做(这不是分支结构的题吗????)
用循环那可是方便太多了,根本不用考虑那么多边界条件,嘎嘎加上去就行了
用循环的思路:
主循环的次数用输入的天数 day 来控制,一共循环 day 次
循环体内用一个分支结构:
如果是星期六,则将星期数加一
如果是星期天,则将星期数重置为1
如果是其他日子,则将星期数加一,实际天数加一
用循环方法的源码1:
#include<iostream> // 引入输入输出流头文件
#include <algorithm>
using namespace std; // 将std命名空间引入到作用域中
int main() // 主函数
{
int start, day; // 定义两个整数变量start和day,分别表示小鱼开始游泳的星期数和总天数
cin >> start >> day; // 从标准输入读取这两个整数
int real_day = 0; // 定义一个整数变量real_day,用于记录小鱼实际游泳的天数
for (int i = 0; i < day; i++) // 外层循环,表示小鱼游泳的总天数
{
if (start == 6 || start == 7) // 如果小鱼开始游泳的那一天是星期六或星期日
{
if (start == 6) // 如果小鱼开始游泳的那一天是星期六
start++; // 则将start加1,变成星期日
else if (start == 7) // 如果小鱼开始游泳的那一天是星期日
start = 1; // 则将start重置为1,表示小鱼从星期一开始游泳
}
else // 如果小鱼开始游泳的那一天不是星期六或星期日
{
start++; // 则将start加1,表示小鱼从下一天开始游泳
real_day++; // 同时将real_day加1,表示小鱼实际游泳的天数增加一天
}
}
// 计算小鱼实际游泳的距离,将real_day乘以每天游泳的距离250
long long distance = real_day * 250;
cout << distance << endl; // 将结果输出到标准输出流
return 0; // 函数返回0,表示正常退出
}
注意在 if (week_day == 6 || week_day == 7) 中,这里不能只用一个if,如果start是6,执行后start会变成7,从而直接执行这句,这样每一轮都会多游泳一天
不起眼的一个小地方就可能会让我们困惑很久,我也是debug了以后才发现 T^T
参考了一下其他大佬的代码,这个思路的代码还可以更简洁一些~
用循环方法的源码2:
#include<iostream> // 引入输入输出流头文件
#include <algorithm> // 引入算法头文件
using namespace std; // 使用标准命名空间
int main() // 主函数
{
int week_day, day; // 定义起始周和天数
int real_day = 0; // 实际游泳的天数(不包括周末)
cin >> week_day >> day; // 输入起始天和天数
for (int i = 0; i < day; i++) // 遍历每一天
{
if (week_day != 6 && week_day != 7) // 如果当前不是周末
real_day++; // 累计游泳天数
if (week_day == 7) // 如果当前是周日
week_day = 1; // 更新起始周为周一
else
week_day++; // 更新起始天为下一天
}
long long distance = real_day * 250; // 计算累计游泳距离
cout << distance << endl; // 输出累计游泳距离
return 0; // 返回 0 表示程序正常结束
}
总结:
正如伟大的维新派——理塘.顶真所言:都什么年代还在用传统分支
我想了一下,其实可以说绝大多数能够用分支解决的,用循环也能解决
比如判断一个数是不是偶数:
用分支写就四条代码
#include <iostream>
using namespace std;
int main() {
int number;
cin >> number;
if ( number % 2 == 0 )
cout << "True" << endl;
else
cout << "False" << endl;
return 0;
}
那么如果用循环来写呢?
#include <iostream>
using namespace std;
int main() {
int number;
cin >> number;
int flag = 1; //用1表示这个数是偶数
for(int i = 0; i < number; i++)
flag = -flag;
if(flag == 1)
cout << "True" << endl;
else
cout << "False" << endl;
return 0;
}
可以看到,虽然代码多了一些,但是也可以解决问题,循环也可以用来处理分支的问题,只是有些情况下,分支更好用罢了~
有些问题没必要在分支上死磕,万一用了循环有奇效呢~
----------------------------------------------------------分割线--------------------------------------------------------------
芜湖~终于写完了~
写这篇文章前前后后花了我快6小时左右,可以说的上是我目前为止写过最长的文章了,如果您觉得我这篇文章对您有帮助的话,那不妨点个赞和收藏呗,谢谢您~
如果您觉得我的文章有问题,请您私信我,我看到后就会及时改正,谢谢您!