[贪心] UVa1612 猜名次(浮点数精度问题)
程序员文章站
2022-06-02 20:25:04
...
题目###
思路
1.读题:本题的题目需要好好理解一下,刚开始给的是ID依次1~ n的得分,然后再给的是rank1~ rank n的ID,题目说的不是很清楚。
2.基本思路就是贪心。为了使后面选手的选择空间更大,rank靠前的选手因尽能力分高,这道题就仅此而已了。另外ID并列的情况也很容易分析,详情可以看代码。
3.本题要考虑浮点数精度的问题。比较明智的做法是,由于给的和输出的都是两位小数,所以输入时乘100,输出时除100。
代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <functional>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
using namespace std;
const int maxn = 20000;
struct node {
int t1, t2, t3, ID;
}A[maxn],B[maxn]; // B为原始输入,A为按rank排好序的
int n;
int score(int last, int i) {
if (i == 0) return A[i].t1 + A[i].t2 + A[i].t3; // 避免出现负下标
int temp[] = { A[i].t1 + A[i].t2 + A[i].t3, A[i].t1 + A[i].t2, A[i].t1 + A[i].t3,
A[i].t2 + A[i].t3, A[i].t1, A[i].t2, A[i].t3, 0 };
sort(temp, temp + 8, greater<int>() ); // sort降序排列的方法,不要忘了()
if (A[i - 1].ID < A[i].ID) {
_for(i, 0, 8) if (last >= temp[i]) return temp[i];
}
else {
_for(i, 0, 8) if (last > temp[i]) return temp[i];
}
return -1;
}
int main() {
int kase = 0;
while (scanf("%d", &n) && n) {
double f1, f2, f3;
_for(i, 0, n) {
scanf("%lf%lf%lf", &f1, &f2, &f3);
B[i].t1 = round(f1 * 100.0);
B[i].t2 = round(f2 * 100.0);
B[i].t3 = round(f3 * 100.0); // 对double读入的处理
B[i].ID = i+1;
}
int t;
_for(i, 0, n){
scanf("%d", &t);
A[i] = B[t-1];
}
int last = 300000 + 100;
_for(i, 0, n) {
last = score(last, i);
if (last == -1) break;
}
if (last == -1) printf("Case %d: No solution\n", ++kase);
else printf("Case %d: %.2f\n",++kase,(double)last/100);
}
return 0;
}
码农小技巧
1.读入的浮点数往往有误差,比如9.53读成9.5299999999这种,这时候为了避免可以使用round函数,其功能是四舍五入。不过讲道理这种误差这么大的情况少见,所以只要记得遇到了可以用round就可以了。
上一篇: 烧纸真管用
下一篇: [达梦数据库]达梦MPP集群搭建