UVA 207 PGA Tour Prize Money

题目链接:https://vjudge.net/problem/UVA-207

题目翻译摘自《算法禁赛入门经典》

题目大意

  你的任务是为PGA(美国职业高尔夫球协会)巡回赛计算奖金。巡回赛分为4轮,其中 所有选手都能打前两轮(除非中途取消资格),得分相加(越少越好),前70名(包括并列)晋级(make the cut)。所有晋级选手再打两轮,前70名(包括并列)有奖金。组委会事 先会公布每个名次能拿的奖金比例。例如,若冠军比例是18%,总奖金是\$1000000,则冠军 奖金是$180000。

  输入保证冠军不会并列。如果第 k 名有 n 人并列,则第 k~n+k - 1 名的奖金比例相加后平均分给这 n 个人。如果 n+k - 1 超过 70,则第 k~70 名的奖金比例相加后平均分给这 n 个人。奖金四舍五入到美分。所有业余选手不得奖金。例如,若业余选手得了第 3 名,则第 4 名会拿第 3 名的奖金比例。如果没取消资格的非业余选手小于70名,则剩下的奖金就不发了。

  输入第一行为数据组数。每组数据前有一个空行,然后分为两部分。第一部分有 71 行 (各有一个实数),第一行为总奖金,第 i+1 行为第i名的奖金比例。比例均保留 4 位小数, 且总和为100%。第 72 行为选手数(最多144),然后每行一个选手。

  业余选手名字后会有一个“*”。犯规选手在犯规的那一轮成绩为DQ,并且后面不再有其他成绩。但是只要没犯规,即使没有晋级,也会给出4轮成绩(虽然在实际比赛中没晋级的 选手只会有两个成绩)。输入保证至少有70个人晋级

  输出应包含所有晋级到后半段(make the cut)的选手。输出信息包括:选手名字、排 名、各轮得分、总得分以及奖金数。没有得奖则不输出,若有奖金,即使奖金是$0.00也要 输出,保留两位小数)。如果此名次至少有两个人获得奖金,应在名次后面加“T”。犯规选 手列在最后,总得分为DQ,名次为空。如果有并列,则先按轮数排序,然后按各轮得分之 和排序,最后按名字排序。两组数据的输出之间用一个空格隔开。

分析

  uDebug 上有误,输入输出要求得按照题目来。
  没什么难度,重点题目里我都标出来了,就是输入输出较烦。

代码如下

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  5 #define Rep(i,n) for (int i = 0; i < (n); ++i)
  6 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
  7 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
  8 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
  9 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
 10 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
 11 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
 12  
 13 #define pr(x) cout << #x << " = " << x << "  "
 14 #define prln(x) cout << #x << " = " << x << endl
 15  
 16 #define LOWBIT(x) ((x)&(-x))
 17  
 18 #define ALL(x) x.begin(),x.end()
 19 #define INS(x) inserter(x,x.begin())
 20  
 21 #define ms0(a) memset(a,0,sizeof(a))
 22 #define msI(a) memset(a,inf,sizeof(a))
 23 #define msM(a) memset(a,-1,sizeof(a))
 24 
 25 #define MP make_pair
 26 #define PB push_back
 27 #define ft first
 28 #define sd second
 29  
 30 template<typename T1, typename T2>
 31 istream &operator>>(istream &in, pair<T1, T2> &p) {
 32     in >> p.first >> p.second;
 33     return in;
 34 }
 35  
 36 template<typename T>
 37 istream &operator>>(istream &in, vector<T> &v) {
 38     for (auto &x: v)
 39         in >> x;
 40     return in;
 41 }
 42  
 43 template<typename T1, typename T2>
 44 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
 45     out << "[" << p.first << ", " << p.second << "]" << "\n";
 46     return out;
 47 }
 48 
 49 inline int gc(){
 50     static const int BUF = 1e7;
 51     static char buf[BUF], *bg = buf + BUF, *ed = bg;
 52     
 53     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
 54     return *bg++;
 55 } 
 56 
 57 inline int ri(){
 58     int x = 0, f = 1, c = gc();
 59     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
 60     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
 61     return x*f;
 62 }
 63 
 64 template<class T>
 65 inline string toString(T x) {
 66     ostringstream sout;
 67     sout << x;
 68     return sout.str();
 69 }
 70 
 71 inline int toInt(string s) {
 72     int v;
 73     istringstream sin(s);
 74     sin >> v;
 75     return v;
 76 }
 77  
 78 typedef long long LL;
 79 typedef unsigned long long uLL;
 80 typedef pair< double, double > PDD;
 81 typedef pair< int, int > PII;
 82 typedef pair< int, PII > PIPII;
 83 typedef pair< string, int > PSI;
 84 typedef pair< int, PSI > PIPSI;
 85 typedef set< int > SI;
 86 typedef set< PII > SPII;
 87 typedef vector< int > VI;
 88 typedef vector< VI > VVI;
 89 typedef vector< SI > VSI;
 90 typedef vector< PII > VPII;
 91 typedef map< int, int > MII;
 92 typedef map< int, string > MIS;
 93 typedef map< int, PII > MIPII;
 94 typedef map< PII, int > MPIII;
 95 typedef map< string, int > MSI;
 96 typedef map< string, string > MSS;
 97 typedef map< PII, string > MPIIS;
 98 typedef map< PII, PII > MPIIPII;
 99 typedef multimap< int, int > MMII;
100 typedef multimap< string, int > MMSI;
101 //typedef unordered_map< int, int > uMII;
102 typedef pair< LL, LL > PLL;
103 typedef vector< LL > VL;
104 typedef vector< VL > VVL;
105 typedef priority_queue< int > PQIMax;
106 typedef priority_queue< int, VI, greater< int > > PQIMin;
107 const double EPS = 1e-8;
108 const LL inf = 0x7fffffff;
109 const LL infLL = 0x7fffffffffffffffLL;
110 const LL mod = 1e9 + 7;
111 const int maxN = 1e4 + 7;
112 const LL ONE = 1;
113 const LL evenBits = 0xaaaaaaaaaaaaaaaa;
114 const LL oddBits = 0x5555555555555555;
115 
116 struct Player{
117     string name;
118     int rank = 0, sc[4], totS = 0;
119     bool isAmateur = false, isTied = false, isDQ = false, hasMoney = false;
120     double bonus = 0;
121     
122     Player() {}
123     Player(string s) {
124         string tmp;
125         name = s.substr(0, 20);
126         if(name.find('*') != string::npos) isAmateur = true;
127         
128         Rep(i, 4) sc[i] = 666666; // 方便排序 
129         
130         Rep(i, 4) {
131             tmp = s.substr(21 + i * 3, 2);
132             if(tmp == "DQ") {
133                 isDQ = true;
134                 break;
135             }
136             else sc[i] = toInt(tmp);
137         }
138         
139         Rep(i, 4) totS += sc[i];
140     }
141     
142     bool operator< (const Player &x) const {
143         if(totS == x.totS) return name < x.name;
144         return totS < x.totS;
145     }
146     
147     void print() {
148         if(isDQ) {
149             name.resize(31, ' ');
150             cout << name;
151             Rep(i, 4) {
152                 if(sc[i] != 666666) printf("%-5d", sc[i]);
153                 else printf("     ");
154             }
155             printf("DQ\n");
156             return;
157         }
158         
159         name += " " + toString(rank);
160         if(isTied && hasMoney) name.PB('T'); // 只有并列且拿钱才需要加 T 
161         name.resize(31, ' ');
162         cout << name;
163         
164         Rep(i, 4) printf("%-5d", sc[i]);
165         
166         if(hasMoney) printf("%-10d$%9.2f\n", totS, bonus / 100 + EPS);
167         else printf("%d\n", totS);
168     }
169 };
170 Player p[150];
171 int num;
172 
173 inline bool cmp(const Player &x, const Player &y) {
174     return x.sc[0] + x.sc[1] < y.sc[0] + y.sc[1];
175 }
176 
177 int T;
178 double totM, preRate[71];
179 
180 int main(){
181     //freopen("MyOutput.txt","w",stdout);
182     //freopen("input.txt","r",stdin);
183     //INIT();
184     scanf("%d\n", &T);
185     while(T--) {
186         scanf("%lf\n", &totM);
187         For(i, 1, 70) {
188             scanf("%lf\n", &preRate[i]);
189             preRate[i] += preRate[i - 1];
190         }
191         
192         scanf("%d\n", &num);
193         For(i, 1, num) {
194             string str;
195             getline(cin, str);
196             p[i] = Player(str);
197         }
198         sort(p + 1, p + 1 + num, cmp);
199         
200         // 选前 70 名 
201         For(i, 71, num) {
202             if(p[i].sc[0] + p[i].sc[1] != p[i - 1].sc[0] + p[i - 1].sc[1]) {
203                 num = i - 1;
204                 break;
205             }
206         }
207         
208         sort(p + 1, p + 1 + num);
209         
210         int i = 1, pcnt = 0; // pcnt 为已经给过奖金的人数 
211         while(i <= num) {
212             if(p[i].isDQ) break;
213             int j = i - 1, cnt = 0;
214             
215             while(j + 1 <= num && p[j + 1].totS == p[i].totS) if(!p[++j].isAmateur) ++cnt;
216             
217             // [i, j] 为分数相同的区间,cnt记录这区间中非业余的人数 
218             For(k, i, j) {
219                 p[k].rank = i;
220                 if(cnt >= 2 && !p[k].isAmateur) p[k].isTied = true;
221                 
222                 if(cnt && pcnt < 70 && !p[k].isAmateur) {
223                     p[k].hasMoney = true;
224                     p[k].bonus = totM * (preRate[min(pcnt + cnt, 70)] - preRate[pcnt]) / cnt;
225                 }
226             }
227             i = j + 1;
228             pcnt += cnt;
229         }
230         
231         printf("Player Name          Place     RD1  RD2  RD3  RD4  TOTAL     Money Won\n");
232         printf("-----------------------------------------------------------------------\n");
233         i = 1;
234         while(i <= num) p[i++].print();
235         if(T) printf("\n");
236     }
237     return 0;
238 }
View Code

 

posted @ 2019-06-20 22:08  梦樱羽  阅读(430)  评论(0编辑  收藏  举报
Live2D