207 - PGA Tour Prize Money (UVA)

题目链接如下:

Online Judge

这可能是目前为止我做过的最恶心的模拟题了。花了我好多时间写代码和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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值