本文主要是介绍AtCoder题解——Beginner Contest 161——B-Popular Vote。血的教训,算法中慎用浮点数比较,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
简单记录一个原则,慎用浮点数比较。
问题由来
给一个朋友忽悠了,去写讲解一下 AtCoder Beginner Contest。既然是讲课,备课肯定是必须的。
题目链接为https://atcoder.jp/contests/abc161/tasks/abc161_b。
Problem Statement
We have held a popularity poll for N items on sale. Item i received Ai votes.
From these N items, we will select M as popular items. However, we cannot select an item with less than of the total number of votes.
If M popular items can be selected, print Yes
; otherwise, print No
.
Constraints
1 ≤ M ≤ N ≤100
1 ≤ Ai ≤ 1000
Ai are distinct.
All values in input are integers.
Input
Input is given from Standard Input in the following format:
N M
A1 ... An
Output
If M popular items can be selected, print Yes
; otherwise, print No
.
Samples
Sample Input 1
4 1
5 4 2 1
Sample Output 1
Yes
There were 12 votes in total. The most popular item received 5 votes, and we can select it.
Sample Input 2
3 2
380 19 1
Sample Output 2
No
There were 400 votes in total. The second and third most popular items received less than of the total number of votes, so we cannot select them. Thus, we cannot select two popular items.
Sample Input 3
12 3
4 56 78 901 2 345 67 890 123 45 6 789
Sample Output 3
Yes
翻车现场
讲真,AtCoder Beginner Contest 这个级别比赛真心不难,比普及组第 4 题的难度略低,尤其是 A、B、C 这三题,基本没有涉及到算法方面。
但是很不幸,这题就翻车了。
错误情况如上图所示,有一个测试用例没有通过。当时就懵逼了,我去,这里都能翻车啊。
这题好简单啊。统计一下就好了。下面是我提交的代码。
#include <bits/stdc++.h>const int MAXN = 100+2;
int nums[MAXN];int main() {int n,m;scanf("%d%d", &n, &m);int sum=0;for (int i=0; i<n; i++) {scanf("%d", &nums[i]);sum += nums[i];}double popular = 1.0/(4*m);int cnt = 0;for (int i=0; i<n; i++) {double v = 1.0*nums[i]/sum;if (v>popular) {cnt++;if (cnt >= m) {printf("Yes\n");return 0;}}}printf("No\n");return 0;
}
当时自己心里说别慌,我们仔细分析。仔细看了一下题目,可能的翻车原因有如下几个:
1、因为使用了,数组越界。查了一下代码,数据越界是不存在的。而且如果数据越界,给的反馈肯定不会是 WA。
2、由于使用了整数转换成浮点数,那么可能是出现了整数除以整数导致小数部分给省略。检查代码,所有整数转浮点数的时候,都已经使用隐式转换,不是这个问题。
我去,这下麻烦大了,不是小细节。我就有点晕了。马上拿出精神,开始写测试对拍程序,然后我们开始开心的拍啊拍。结果拍了十几分钟,没有问题出现。懵逼状态开始如下变化。
到,随着对拍时间持续,变成,最后到达。我的天哪,难道题目里有大 Boss。
我静下来,再次一行一行阅读了代码。看到比较的时候,突然灵感闪现。标准浮点数比较是需要用精度比较,而不能直接用符号比较的,因为涉及到精度问题。其他地方不可能出现问题的。好的,立马将代码改成整数比较。
#include <bits/stdc++.h>const int MAXN = 100+2;
int nums[MAXN];int main() {int n,m;scanf("%d%d", &n, &m);int sum=0;for (int i=0; i<n; i++) {scanf("%d", &nums[i]);sum += nums[i];}int cnt = 0;for (int i=0; i<n; i++) {if (nums[i]*4*m>=sum) {cnt++;if (cnt >= m) {printf("Yes\n");return 0;}}}printf("No\n");return 0;
}
再次提交。绿色的 AC 出现。
苍天啊。果然是细节。特此记录。慎用浮点数比较。
这篇关于AtCoder题解——Beginner Contest 161——B-Popular Vote。血的教训,算法中慎用浮点数比较的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!