Uva 1612 Guess

Thinking about it:

  题目要求最后一名(也就是第N位)的分数要尽量的大,那么就一定要求第N-1名的分数也要尽量大。假如N-1可以取400和500,那么N-1应该取500,如果取400,可能第N位就不能取450,而只能取350了,这样不满足要求。综上,可以从第1位开始,分数尽量取高一点,依次类推,一直取道最后。假设第N-1位的 id 为 a,第 N 位的 id 为 b,如果 a < b,那么第N位可以取与第N-1位相同的分数,否则只能取比第N-1位的分数小的而又尽量大的数(题目中有描述:If two players got the same total score, the one with the smaller ID number got a higher rank)。如果没有符合上述条件的数可以取,那么就是"No solution"。

  这题有一个注意点:输入的分数是浮点数,而且最多有两个小数点。为了尽可能避免浮点数带来的误差,可以将分数*100后转化为整数处理,在输出时再除以100。

Reference:

  http://acm.lilingfei.com/uva-1612-guess-%E4%B9%A0%E9%A2%988-8_104

PS:

  开始处理这题时,我自信满满,因为我认为我的思路是对的。后来证明,思路确实是对的。但问题就出在浮点数处理上,而且我一直没发现这个问题,直至我查阅了大神的代码才知道处理浮点数的技巧。所以:能把浮点数转化位整数的话,就把它转化为整数处理吧。

Code:

/**
 * AC @ Sep 18th 2015
 * Run Time : 0.073s
 */
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 20000 + 50;
int ord[MAXN];
std::vector<int> score[MAXN];
// count from 1
int N;

void read() {
    double x, y ,z;
    for (int i = 1; i <= N; ++i) {
        cin >> x >> y >> z;
        // the operations about precision is surprisingly vital,
        // especially the round function
        int a = (int)round(x * 100);
        int b = (int)round(y * 100);
        int c = (int)round(z * 100);
        // initialize the score[i] at the same time
        score[i] = {0, a, b, c, a + b, a + c, b + c, a + b + c};
        sort(score[i].begin(), score[i].end());
    }
    for (int i = 1; i <= N; ++i) {
        cin >> ord[i];
    }
}

int find(int id, int value, int former_id) {
    for (int i = (int)score[id].size() - 1; i >= 0; -- i) {
        if (value == score[id][i] && id > former_id) {
            return value;
        } else if (value > score[id][i]) {
            return score[id][i];
        }
    }
    return -1;
}

int done() {
    int guess = score[ord[1]][ score[ord[1]].size() - 1 ];
    for (int i = 2; i <= N; ++i) {
        guess = find(ord[i], guess, ord[i - 1]);
        if (guess == -1) {
            return -1;
        }
    }
    return guess;
}

int Case = 0;
void work() {
    read();
    int ans = done();
    cout << "Case " << (++Case) << ": ";
    if (ans == -1) {
        cout << "No solution" << endl;
    } else {
        cout << fixed << setprecision(2) << (ans / 100.0) << endl;
    }
}

int main(int argc, char const *argv[]) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    while (cin >> N && N) {
        work();
    }
    return 0;
}