题目链接如下:
这可能是目前为止我做过的最恶心的模拟题了。花了我好多时间写代码和debug。(以后不想浪费这么多时间在这种没啥意义的事上了……by the way, 现在洛谷上这道题的通过量只有70多个,可见这道题公认恶心。)
一开始总是runtime error,我找不到原因;后来抱着尝试的心态,修改了第20行数组长度,从100到200, int rankNbr[200]; 居然就没runtime error了……这个点真的很隐蔽,因为前两轮后把人数砍到70以及tie,一般会默认肯定小于100……没想到还有可能超出100,太坑了。
代码如下,因为题目太恶心了,我就没心情再想办法优化代码了,就这样吧:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
// #define debug
struct player{
std::string name;
int score[6] = {-1, -1, -1, -1, 0, 0};
int round = 4;
int rank = -1;
bool isTieScore = false;
double prize = -1;
bool isAmateur = false;
player(){}
player(std::string _name): name(_name){}
};
int n, m, tieScore;
int rankNbr[200];
double purse;
double percent[71];
std::string line, name;
std::vector<player> ans;
bool cmp1(const player &a, const player &b){
return a.score[4] < b.score[4];
}
bool cmp2(const player &a, const player &b){
if(a.round != b.round){
return a.round > b.round;
}
if(a.score[5] != b.score[5]){
return a.score[5] < b.score[5];
}
return a.name < b.name;
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("3.txt", "w", stdout);
#endif
scanf("%d", &n);
for(int kase = 0; kase < n; ++kase){
ans.clear();
std::fill(rankNbr, rankNbr + 100, 0);
printf("%s", kase ? "\n" : "");
std::cout << "Player Name Place RD1 RD2 RD3 RD4 TOTAL Money Won" << std::endl;
std::cout << "-----------------------------------------------------------------------" << std::endl;
scanf("%lf", &purse);
for(int i = 1; i <= 70; ++i){
scanf("%lf", &percent[i]);
}
scanf("%d\n", &m);
for(int i = 0; i < m; ++i){
getline(std::cin, line);
if(isalpha(line[21]) || isalpha(line[24])){
continue;
}
name = line.substr(0, 20);
ans.push_back(player(name));
for(int j = name.size() - 1; j >= 0; --j){
if(name[j] != ' '){
if(name[j] == '*'){
ans.back().isAmateur = true;
}
break;
}
}
for(int j = 0; j < 4; ++j){
if(isalpha(line[21 + j * 3])){
ans.back().round = j;
break;
}
std::string temp = line.substr(20 + 3 * j, 3);
ans.back().score[j] = atoi(temp.c_str());
ans.back().score[5] += ans.back().score[j];
}
ans.back().score[4] = ans.back().score[0] + ans.back().score[1];
}
sort(ans.begin(), ans.end(), cmp1);
if(ans.size() > 70){
int sz = 70;
tieScore = ans[69].score[4];
for(int i = 70; i < ans.size() ; ++i){
if(ans[i].score[4] != tieScore){
break;
}
++sz;
}
ans.resize(sz);
}
sort(ans.begin(), ans.end(), cmp2);
int currRank = 1;
ans[0].rank = 1;
rankNbr[currRank]++;
for (int i = 1; i < ans.size(); ++i){
if (ans[i].round != 4){
break;
}
if (ans[i].score[5] != ans[i - 1].score[5]){
currRank = i + 1;
}
ans[i].rank = currRank;
if (!ans[i].isAmateur){
rankNbr[currRank]++;
}
}
int p = 1;
int temp = 0;
double currPrize;
for (int i = 0; i < ans.size(); ++i){
if (ans[i].rank == -1){
break;
}
if (rankNbr[ans[i].rank] > 1 && !ans[i].isAmateur){
ans[i].isTieScore = true;
}
if (!ans[i].isAmateur){
if (!temp){
if(p > 70){
break;
}
temp = rankNbr[ans[i].rank];
currPrize = 0.0;
for(int j = 0; j < temp; ++j){
if(p > 70){
break;
}
currPrize += purse * percent[p] / 100;
p++;
}
currPrize /= temp;
}
ans[i].prize = currPrize;
--temp;
}
}
for(int i = 0; i < ans.size(); ++i){
std::string str = ans[i].name + " ";
if (ans[i].rank != -1){
str += std::to_string(ans[i].rank);
if(ans[i].isTieScore && ans[i].prize > -1){
str += "T";
}
}
while (str.size() < 31){
str += " ";
}
for(int j = 0; j < 4; ++j){
if (ans[i].score[j] != -1){
str += std::to_string(ans[i].score[j]);
}
while (str.size() < 36 + 5 * j){
str += " ";
}
}
if (ans[i].round == 4){
str += std::to_string(ans[i].score[5]);
} else {
str += "DQ";
}
if(ans[i].prize > -1){
while (str.size() < 61){
str += " ";
}
str += "$";
char ss[20];
sprintf(ss, "%9.2f", ans[i].prize);
std::string ts = ss;
str += ts;
}
std::cout << str << std::endl;
}
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}