因为一共只有三道题,所以每个人的得分最多有8种可能性。把这8种可能性都算出来,存在数组里,排好序备用
排名就是一个天然的链表,给出了扫描的顺序
扫描时,维护两个变量:前一个player的最大得分 recd 和他的ID recdID
扫描到每个player时,从大到小遍历他的8种得分,如果有等于recd的得分,且这个player的ID大于recdID,则只需更新recdID。否则遇到第一个小于recd的得分,就更新recd和recdID。
如果在遍历完8种得分后,还没有满足上面两种情况的,则说明无解
最后只需打印recd的值即可。要注意float型变量相等的判断方法。
在UVa Board中,Brian Fry给了一个很好的提示:尝试不用float。一看得分的范围:10^3,两位小数,则可以果断的乘100得到一个范围为10^5的int。这样出错的机会又少了很多。最后除以100.0输出即可
Run Time: 0.172s
#define UVa "8-8.1612.cpp" //Guess
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
void calc_scores(vector<int>& v, int* a, int d, int maxd, int sum) { //get all 8 possibilities
if(d == maxd)
v.push_back(sum);
else {
calc_scores(v, a, d+1, maxd, sum+a[d]);
calc_scores(v, a, d+1, maxd, sum);
}
}
struct Player{
vector<int> scores;
int ID;
Player(){}
Player(int* a, int id):ID(id){
calc_scores(scores, a, 0, 3, 0);
sort(scores.begin(), scores.end());
}
};
//Global Variables. Reset upon Each Case!
const int maxn = 20000;
int n;
int rank[maxn];
/
int main() {
int kase = 1;
while(scanf("%d", &n) && n) {
memset(rank, -1, sizeof(rank));
Player q[maxn];
float data_fl[3];
int data_int[3];
for(int i = 0; i < n; i ++) {
for(int j = 0; j < 3; j ++) {
scanf("%f", &data_fl[j]);
data_int[j] = (int)(round((data_fl[j] * 100.0)));
}
Player& p = q[i];
p = Player(data_int, i);
}
for(int i = 0; i < n; i ++) scanf("%d", &rank[i]);
int recd = 1000000;
int recdID = -1;
for(int i = 0; i < n; i ++) {
Player& u = q[rank[i]-1];
int ok = 0;
for(int j = 7; j >= 0; j --) { //from large to small
if(u.scores[j] == recd && u.ID > recdID) { //same score, larger ID.
recdID = u.ID;
ok = 1;
break;
}
else if(u.scores[j] < recd) { //smaller score.
recd = u.scores[j];
recdID = u.ID;
ok = 1;
break;
}
}
if(!ok) {
recd = -1;
break;
}
}
if(recd == -1) printf("Case %d: No solution\n", kase++);
else printf("Case %d: %.2f\n", kase++, recd/100.0);
}
return 0;
}