[贪心] UVa1612 猜名次(浮点数精度问题)

题目###这里写图片描述

思路

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就可以了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值