思路分享——hdu 3233

咳咳,此乃本博主第一文。所以前面一大段全部会是废话,想看题目与思路请麻烦往下翻翻。

作为算法竞赛刚刚入门的新手,刷的题目是真的少,所以我是真的菜。。。
我在CSDN上查过不少题目,emmmmm,大部分大佬都是给出题目出处,然后上代码,作为萌新,我有时真的头疼,就算大佬们的代码可读性高,该看不懂还是看不懂啊╮(╯﹏╰)╭。我去查那个题目,我是只要答案吗,人家更想要解析好吧。读书读了这么多年了,在数学上是真的没什么成绩,,,连简单的数学思维也没有,有时候绕着题目,案例,连最后一点逻辑也会丧失。。。。。。
当然,我把这归结为刷的题目实在是太少了。在接触算法竞赛的这不足半年的时间里,我恐怕加起来是一千行代码都没打过。
想送给与我一般刚刚踏入算法竞赛的萌新们一句话:别放弃,你不会,只是你努力得还不够。大家一起,为了成为杰出的程序员而努力吧。
一个杰出的程序员就得有好的计算思维和逻辑思维,所以,我比较想与大家分享的,主要还是我的思路。

来,首先先看hdu的3233题:http://acm.hdu.edu.cn/showproblem.php?pid=3233

此题呢,是让我们模仿下载器,题目给了总文件数T,能同时下载的文件数n,以及下载速度B。下面跟T行,每行首先有一个s表示这个文件总共占多少兆,然后跟一个p表示这个已经下载完了百分之多少。然后让我们输出总共要下载的时间。

审完题,首先就会想到,每行的s*(100-p)/100就表示那个文件还需要下载多少兆。

然后怎么算呢?像题目描述的那样找最小然后加起来再更新数据再找最小直到全下完?仿佛也不是不可以,但是,我算着算着,感觉到不对劲,感觉自己是不是绕了好多弯子。
但是题目给的第一个案例不太直观,于是,我就自己弄了一个案例。如下:
(花里胡翘的计算实际要下载多少兆就省去,我下面就直接放实际要下多少兆)

  • T=4,n=2,B=10;
  • 5
  • 10
  • 15
  • 20
    题目说,并行下载的时候,宽带流量要分摊,也就是说,我n个文件一起下载的时候,下载的速度就为B/n。
    首先,我们找最小的n个,就是5和10,然后下载速度为5,一秒后,第一个文件下载完了,更新一下数据,原来的10会变成5,然后找到15,再一起并行下载,一秒后,第二个文件也会下完,更新数据,原来的15会变成10,然后找到20。两秒后,第三个文件下完,更新数据,20变10,此时只剩下第四个文件了,只下载这一个文件,流量就全砸它上面,一秒下完最后的10兆。所以总时间加起来呢,是1+1+2+1=5(秒)。
    我们把数据理一下就会发现,我们第一秒内,总共下载了10兆,第二秒内,总共下载的10兆,第三秒与第四秒,总共下了20兆,第五秒,下了10兆。
    十分的有规律,哈哈,我总共下了50兆,总共花了5秒。聪明的你们发现了什么,我们要求的这时间,不就等于我需要下载的总兆数除上我宽带的速度嘛。也就是说,这个题目,计算完总兆,直接除去B就行,同时下载数n?这玩意重要吗???
    当然,聪明的具有数学思维的同学,逻辑思维稍微强一点的同学,看到题目要求的“宽带由所有正在下载的文件平均共享”估计就知道是总兆除速度了,没办法,我们这些还没有形成这种逻辑思维的小伙伴们还是要多想几步才想得到。但是没关系嘛,咱们一步一步来,迟早能达到一眼看穿题目的程度的。✧(≖ ◡ ≖✿ 。

然后呢,就是此题的注意事项了。我每次都是理完思路后再审一遍题去挑注意事项,我的小脑子做不到一边注意这些事项一边思考╮(╯﹏╰)╭。

  • 首先看参数范围。
    T是1到20000的整数,嗯,int就够了,然后,T如果等于2000,就意味着,下面至少会输入4000次(每行一个s一个p)。所以绝对绝对绝对不能用cin,绝对超时的节奏哇,得用scanf。因为呢,cin虽然比scanf写起来方便,但其实比scanf效率低,它速度比scanf慢很多。一旦题目需要大量输入,就绝对是TLE(超时,Time Limit Exceeded)卡死你的点。输出的cout和printf也是同样的道理。所以这题呢,我是直接用c写了。
    n是1到2000整数,嗯,int。这个题目和n是真的没关系,如果这个题目所描写的是真实的状况的话,也就是说,我下载东西的时候把同时下载数调再高也没有用,反而会拖累单个文件的下载速度,想起来就觉得太坑了,我的腾讯会员可同时下载三个视频有屁用啊我摔!(╬ ̄皿 ̄)=○
    B是50到1000,emmmmm,上面的案例不符合哈哈哈哈,不过不重要了,自己为了理清题目创的案例简单最重要嘛。反正思路是理清了。嗯,int。
    s,小于20000的非负浮点数,float,那么总兆也应该是个浮点数,不过总文件高达2000个的话,总兆最多可能会达到20000*20000,嗯,此处应该用double(因为改成float就过不了。。。)。这里博主也是钻过牛角尖的,两万乘两万不就2e16吗,float不是有2e128嘛,为毛用float不让过,为什么!!!后来想想,可能不是范围的问题而是精度的问题,float精度达7,double精度达16,也许此题需要的精度高一点。。。咱也不知道,咱也不敢问(⊙_⊙)。然后建议呢,参与计算的,不,题目中出现的浮点数呢,别管什么范围了一率double吧。至于范围超过了double的范围的数,就不建议用c啊c++写了,,,麻烦死了,介意用Java或者Python处理大数。一位杰出的程序员应该掌握多种编程语言,不会的话,emmmmm,博主这边还是介意去学呢。
    p,1到100的整数,int。

  • 然后注意输入结束方式。
    一般有三种:
    1.默认结束。就是以文件结束(EOF)作为结束标志。
    2.有t或者n来确定数据组数的。
    3.以特定元素作为结束符的,一般是0。
    此题属于第三种,以“0 0 0”结尾。

  • 然后注意输出格式,空格啊换行啊什么的。

最后的最后,上代码:(s是float能过博主试过了,但是如果比赛中的话呢,建议直接用double,别冒这个险叭,错一次划不来诶)

#include<stdio.h>
int main() {
	int t, n, b, p;
	float s;
	int cnt = 1;
	while (~scanf("%d%d%d", &t, &n, &b) && t && n && b) {
		double sum=0;
		while (t--) {
			scanf("%f%d", &s, &p);
			sum += s * (100 - p) / 100;
		}
		printf("Case %d: %.2f\n\n", cnt++, sum / b);
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值