紫書_例5-10 UVa207

时间:2023-03-08 23:13:25
紫書_例5-10 UVa207

  細節較多,自己寫的第一份半殘品,未能AC,后參考了劉老師的代碼,寫出了第二份的代碼,經過多次修改后總算AC,然而後果也很嚴重,導致代碼和劉老師極其相似,這也是我不喜歡看了參考代碼后再自己寫的緣故。

祇爲怕自己忘記,所以寫博客留檔

1:一開始沒看題,就看劉老師的描述,我以爲輸入的選手信息沒有規定格式,所以第一份寫了找第一個數字的函數來確定名字與成績的分界綫,后看(翻譯)了題目才知道對輸入是有規範的,并且udebug的隨機數據的名字用P+數字描述,讓我寫的讀取信息的一系列操作作廢了;

2:即使看描述,也把劉老師說的很多細節忽略了,後來看到書上都有講,真是弱智了:

No1,對選手的排名,是至少有兩名獲得獎金的并列情況才加'T';

No2,輸出的選手信息不包括沒晉級的,一開始我把全部選手都輸出了。。。;

No3,獎金是順延的,并不是第二名打星,第三名還是拿第三名的獎金,而是第三名拿第二名的獎金;

No4,排序時候,若總分相同,則按照名字的字典序排序;

3:題目在獎金上面的測試數據不需要+eps來解決精度問題,反而隨機數據裏面會出現精度問題;

4:udebug隨機數據不符合劉老師的描述,所以劉老師的代碼不能跑隨機數據;

自己的和劉老師的代碼都貼出來==兩個雖然長得很像

我的代碼:

 #define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cctype>
#include<utility>
#include<cassert>
#include<cmath>
using namespace std; #define FOR(i,n) for(int i=0;i<(n);i++) const int maxn = ;
const int n_cut = ;
double eps = 1e-;
double money[n_cut], totle;
int n; struct Lan {
char name[];
int rd[], sc36, sc72, dq;
int rnds;
bool star; Lan operator =(string &s) {
FOR(i, ) name[i] = s[i];
name[] = ;
star = false;
if (strchr(name,'*'))
star = true;
sc36 = sc72 = dq = rnds = ;
memset(rd, , sizeof(rd));
FOR(i, ) {
char t[];
FOR(j, ) t[j] = s[ + i * + j];
t[] = '\0';
if (!(sscanf(t, "%d", &rd[i]))) {
dq = -;
rnds = i;
if (i < )
sc36 = -;
break;
}
else {
sc72 += rd[i];
if (i < )
sc36 += rd[i];
}
}
return *this;
}
Lan() {
memset(name, , sizeof(name));
FOR(i, ) rd[i] = ;
sc36 = sc72 = dq =rnds= ;
star = false;
}
}lan[maxn]; void print_result() {
printf("Player Name Place RD1 RD2 RD3 RD4 TOTAL Money Won\n-----------------------------------------------------------------------\n");
int i = , cnt = ;
while (i < n) {
if (lan[i].dq) {
printf("%s ", lan[i].name);
FOR(k, lan[i].rnds)
printf("%-5d", lan[i].rd[k]);
FOR(j, - lan[i].rnds)
printf(" ");
printf("DQ\n");
i++;
continue;
}
int j = i, m = , top = i + ;
double tot = 0.0;
bool have_money = false;
while (j < n&&lan[i].sc72 == lan[j].sc72) {
if (!lan[j].star) {
m++;
if (cnt < n_cut) {
tot += money[cnt++];
have_money = true;
}
}
j++;
}
double totmoney = totle*tot / m;
while (i < j) {
printf("%s ", lan[i].name);
char t[];
sprintf(t, "%d%c", top, (m> && have_money&& !lan[i].star) ? 'T' : ' ');
printf("%-10s", t);
FOR(k, )
printf("%-5d", lan[i].rd[k]);
if (!lan[i].star&&have_money) {
printf("%-10d", lan[i].sc72);
printf("$%9.2f\n", totmoney / 100.0);
}
else
printf("%d\n", lan[i].sc72);
i++;
}
}
} int main() {
int T;
cin >> T;
while (T--) {
cin >> totle;
FOR(i, ) {
cin >> money[i];
}
cin >> n;
assert(n <= );
string s;
getline(cin, s);
FOR(i, n) {
getline(cin, s);
lan[i] = s;
}
sort(lan, lan + n, [](const Lan& t1, const Lan& t2) {
if (t1.sc36 < && t2.sc36 < ) return false;
if (t1.sc36 < ) return false;
if (t2.sc36 < ) return true;
return t1.sc36 < t2.sc36; });
//assert(lan[n_cut-1].sc36 >= 0);
int len = ;
for (; len < n;len++)
if (lan[len].sc36<)
break;
if (len <= n_cut)
n = len;
else
for (int i = n_cut-; i < n; i++)
if (i == n - || lan[i].sc36 != lan[i + ].sc36||lan[i].sc36<) {
n = i + ;
break;
}
sort(lan, lan + n, [](const Lan& t1, const Lan& t2) {
if (t1.dq&&t2.dq) {
if (t1.rnds != t2.rnds)return t1.rnds>t2.rnds;
if(t1.sc72!=t2.sc72) return t1.sc72 < t2.sc72;
return strcmp(t1.name,t2.name) < ;
}
if (t1.dq) return false;
if (t2.dq) return true;
if (t1.sc72 != t2.sc72) return t1.sc72 < t2.sc72;
return strcmp(t1.name,t2.name)< ; });
print_result();
if(T) putchar('\n');
}
return ;
}

劉老師的代碼:

 // UVa207 PGA Tour Prize Money
// Rujia Liu
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cassert>
using namespace std; #define REP(i,n) for(int i = 0; i < (n); i++) const int maxn = ;
const int n_cut = ; struct Player {
char name[];
int amateur;
int sc[];
int sc36, sc72, dq;
int rnds;
} player[maxn]; int n;
double purse, p[n_cut]; bool cmp1(const Player& p1, const Player& p2) {
if(p1.sc36 < && p2.sc36 < ) return false; // equal
if(p1.sc36 < ) return false; // p2 smaller
if(p2.sc36 < ) return true; // p1 smaller
return p1.sc36 < p2.sc36;
} bool cmp2(const Player& p1, const Player& p2) {
if(p1.dq && p2.dq) {
if(p1.rnds != p2.rnds) return p2.rnds < p1.rnds;
if(p1.sc72 != p2.sc72) return p1.sc72 < p2.sc72;
return strcmp(p1.name, p2.name) < ;
}
if(p1.dq) return false;
if(p2.dq) return true;
if(p1.sc72 != p2.sc72) return p1.sc72 < p2.sc72;
return strcmp(p1.name, p2.name) < ;
} void print_result() {
printf("Player Name Place RD1 RD2");
printf(" RD3 RD4 TOTAL Money Won\n");
printf("---------------------------------------");
printf("--------------------------------\n"); int i = , pos = ;
while(i < n) {
if(player[i].dq) {
printf("%s ",player[i].name);
REP(j,player[i].rnds) printf("%-5d", player[i].sc[j]);
REP(j,-player[i].rnds) printf(" ");
printf("DQ\n");
i++;
continue;
} int j = i;
int m = ; // number of tied players
bool have_money = false;
double tot = 0.0; // total pooled money
while(j < n && player[i].sc72 == player[j].sc72) {
if(!player[j].amateur) {
m++;
if(pos < n_cut) {
have_money = true; // yeah! they still have money
tot += p[pos++];
}
}
j++;
} // print player [i,j) together because they have the same rank
int rank = i + ; // rank of all these m players
double amount = purse * tot / m; // if m=0, amount will be nan but we don't use it in that case :)
while(i < j) {
printf("%s ", player[i].name);
char t[];
sprintf(t, "%d%c", rank, m > && have_money && !player[i].amateur ? 'T' : ' ');
printf("%-10s", t);
REP(e,) printf("%-5d", player[i].sc[e]); // with prize
if(!player[i].amateur && have_money) {
printf("%-10d", player[i].sc72);
printf("$%9.2lf\n", amount / 100.0);
} else
printf("%d\n", player[i].sc72);
i++;
}
}
} int main() {
int T;
char s[]; gets(s);
sscanf(s,"%d",&T);
while(T--) {
gets(s); // empty line // prize
gets(s);
sscanf(s,"%lf", &purse);
REP(i,n_cut) {
gets(s);
sscanf(s, "%lf", &p[i]);
} // players
gets(s);
sscanf(s, "%d", &n);
assert(n <= );
REP(k,n) {
// read a 32-character line
gets(s); // player name
strncpy(player[k].name, s, );
player[k].name[] = ;
player[k].amateur = ;
if(strchr(player[k].name, '*')) {
player[k].amateur = ;
} // scores
player[k].sc36 = player[k].sc72 = player[k].dq=;
memset(player[k].sc, -, sizeof(player[k].sc));
REP(i,) {
// raw score
char t[];
REP(j,) t[j] = s[ + i* + j]; t[] = '\0'; // parse
if(!sscanf(t,"%d", &player[k].sc[i])) {
// DQ!
player[k].rnds = i;
player[k].dq = -;
if(i < ) player[k].sc36 = -;
break; // skip other rounds (filled with -1, initially)
} else {
player[k].sc72 += player[k].sc[i];
if(i < )
player[k].sc36 += player[k].sc[i];
}
}
} // round 1
sort(player, player+n, cmp1);
assert(player[n_cut-].sc36 >= );
for(int i = n_cut-; i < n; i++)
if(i == n- || player[i].sc36 != player[i+].sc36) { n = i+; break; } // round 2
sort(player, player+n, cmp2); // print result
print_result(); if(T) printf("\n");
} return ;
}