POJ1030 Rating
题目来源:http://poj.org/problem?id=1030
题目大意:有100支队伍(编号1->100),有两场比赛。以下表的形式列出了两场比赛的名次。(有的队伍没有参赛或只参加了一场比赛。)
要求两场比赛的总排名。计算规则是:
1.如果某队两场都比另一队排名靠前(或一场赢一场平),则总排名靠前。
2.如果两队在两场比赛中各赢一场,则他们的排名取决于他们在两场比赛中的排名差。如上面的例子中1队在比赛1中赢了5队,名次差为3,在比赛2中输给5对,名次差为1,所以1队应排在5队前面。如果两个名次差相等,则两队的总排名相等。两队两场比赛都平局时总排名也相等。
3.对于只参加了一次比赛的队伍,他们的最终排名不一定能够确定。他们能否进入最终名单由下面的规则决定:
A) 如果存在某支队伍参加了两场比赛,与该队伍平局,那么这个队伍的排名与这支参加两场的排名一致。如果有多支这样的队伍,他们的排名应该完全相同,否则所有的队伍排名都不能决定。
B) 如果能为只参加了一场比赛c的一支队伍A找到一个位置,使得这个位置之前的队伍在c中都赢了A,该位置之后的队伍在c中都输给A,则可以把A插入到该位置,如果有多个队伍可以插到该位置,按他们在各自比赛中获得的名次决定先后顺序或并列。
对于上面图片所示的例子,分析过程如下:
Team 3 will occupy the first place in the overall list (rule B).
The positions of teams 6 and 7 cannot be determined.
Team 10 will share the overall rating with team 1 (rule A).
Team 20 will share the overall rating with team 4 (rule A).
Team 19 will occupy the position between teams 9, 5 and team 4 (rule B).
Teams 8, 15, 17, 18, 21, and 31 will finish the overall list (rule B). But the first of them will be teams 15 and 8 (that took 6th place) followed by teams 31 and 18 (that took 8th place) and teams 17 and 21 (that took 10th place).
程序的目标是由两场比赛的排名求总排名。
输入:两场比赛中表格中team's id部分。
输出:同样形式的总排名。
Sample Input
6 9 7 1 4 5 15 8 31 18 17 8 3 5 1 10 6 9 19 4 20 21
Sample Output
3 1 10 5 9 19 4 20 8 15 18 31 17 21
我的程序写得比较复杂了,按照每条规则为每个队伍找排名。一个处理是在计算时把排名设定为浮点数而不是整数,这样在进行插入的时候不会需要移动很多队伍的名次,最要最后整理的时候映射为整数即可。
1 ////////////////////////////////////////////////////////////////////////// 2 // POJ1030 Rating 3 // Memory: 320K Time: 94MS 4 // Language: C++ Result: Accepted 5 ////////////////////////////////////////////////////////////////////////// 6 7 #include <iostream> 8 #include <stdio.h> 9 #include <map> 10 #include <list> 11 12 using namespace std; 13 14 int cnt[101]; 15 int rank1[101]; 16 int rank2[101]; 17 float rank[101]; 18 float buff[101]; 19 bool tag[101]; 20 map<int, list<int>> record1; 21 map<int, list<int>> record2; 22 int k1, k2; 23 24 struct Rate { 25 float rank; 26 list<int> teams; 27 Rate * next; 28 }; 29 Rate * head = NULL; 30 31 float compRank(Rate * a, Rate * b) { 32 return a->rank - b->rank; 33 } 34 bool cmp(const void * a, const void * b) { 35 return *(int *)a > *(int *)b ? true : false; 36 } 37 void exchangeRank(Rate *a, Rate * b) { 38 float rank = a->rank; 39 list<int> teams = a->teams; 40 a->rank = b->rank; 41 a->teams = b->teams; 42 b->rank = rank; 43 b->teams = teams; 44 } 45 void sortRank() { 46 if (head == NULL || head->next == NULL) { 47 return; 48 } 49 Rate * key = head->next; 50 Rate * p = head; 51 while (key != NULL) { 52 while (p != key) { 53 if (compRank(p, key) > 0) { 54 exchangeRank(p, key); 55 } 56 p = p->next; 57 } 58 p = head; 59 key = key->next; 60 } 61 } 62 void readData() { 63 char buf[10000]; 64 int teamId; 65 int teamCnt; 66 char * pCur; 67 int rankSum = 0; 68 int rankCur = 0; 69 70 gets(buf); 71 sscanf(buf, "%d", &k1); 72 for (int i = 0; i < k1; ++i) { 73 gets(buf); 74 rankCur = rankSum + 1; 75 pCur = strtok(buf, " "); 76 list<int> ts; 77 while (pCur) { 78 ++rankSum; 79 teamId = atoi(pCur); 80 ++cnt[teamId]; 81 rank1[teamId] = rankCur; 82 ts.push_back(teamId); 83 pCur = strtok(NULL, " "); 84 } 85 record1[rankCur] = ts; 86 } 87 getchar(); 88 gets(buf); 89 sscanf(buf, "%d", &k2); 90 rankSum = rankCur = 0; 91 for (int i = 0; i < k2; ++i) { 92 gets(buf); 93 rankCur = rankSum + 1; 94 pCur = strtok(buf, " "); 95 list<int> ts; 96 while (pCur) { 97 ++rankSum; 98 teamId = atoi(pCur); 99 ++cnt[teamId]; 100 rank2[teamId] = rankCur; 101 ts.push_back(teamId); 102 pCur = strtok(NULL, " "); 103 } 104 record2[rankCur] = ts; 105 } 106 } 107 108 void cc2() { 109 for (int i = 1; i <= 100; ++i) { 110 if (cnt[i] == 2) { 111 rank[i] = rank1[i] + rank2[i]; 112 } 113 } 114 for (int i = 1; i <= 200; ++i) { 115 Rate * rate = new Rate; 116 rate->rank = i; 117 for (int j = 1; j <= 100; ++j) { 118 if (rank[j] == i) { 119 rate->teams.push_back(j); 120 } 121 } 122 if (!rate->teams.empty()) { 123 rate->next = head; 124 head = rate; 125 } 126 } 127 } 128 129 void cc1() { 130 for (int i = 1; i <= 100; ++i) { 131 if (cnt[i] != 1) { 132 continue; 133 } 134 int r; 135 int p; 136 if (rank1[i] != 0) { 137 r = rank1[i]; 138 p = 1; 139 } else { 140 r = rank2[i]; 141 p = 2; 142 } 143 int count = 0; 144 list<int> temp; 145 if (p == 1) { 146 temp = record1[r]; 147 } else { 148 temp = record2[r]; 149 } 150 list<int> eq; 151 for (list<int>::iterator it = temp.begin(); it != temp.end(); ++it) { 152 if (cnt[*it] == 2) { 153 eq.push_back(*it); 154 } 155 } 156 if (!eq.empty()) { 157 int rc = rank[eq.front()]; 158 bool flag = true; 159 for (list<int>::iterator it = eq.begin(); it != eq.end(); ++it) { 160 if (rank[*it] != rc) { 161 rank[i] = 0; 162 flag = false; 163 break; 164 } 165 } 166 if (flag == true) { 167 for (Rate * p = head; p != NULL; p = p->next) { 168 if (p->rank == rc) { 169 p->teams.push_back(i); 170 break; 171 } 172 } 173 } 174 } else { 175 tag[i] = true; 176 } 177 } 178 for (int i = 1; i <= 100; ++i) { 179 if (tag[i] != true) { 180 continue; 181 } 182 int p; 183 int r; 184 if (rank1[i] != 0) { 185 r = rank1[i]; 186 p = 1; 187 } else { 188 r = rank2[i]; 189 p = 2; 190 } 191 int * temp = (p == 1) ? rank1 : rank2; 192 int prior = -1; 193 int next = 101; 194 for (int j = 1; j <= 100; ++j) { 195 if (temp[j] != 0 && temp[j] < r && rank[j] != 0) { 196 if (rank[j] > prior) { 197 prior = rank[j]; 198 } 199 } 200 if (temp[j] != 0 && temp[j] > r && rank[j] != 0) { 201 if (rank[j] < next) { 202 next = rank[j]; 203 } 204 } 205 206 } 207 if (next > prior) { 208 buff[i] = (next + prior) / 2.0; 209 } 210 } 211 } 212 213 void insertcc1() { 214 for (int i = 1; i <= 100; ++i) { 215 if (buff[i] == 0) { 216 continue; 217 } 218 float fr = buff[i]; 219 Rate * p = head; 220 Rate * rate = new Rate; 221 rate->rank = fr; 222 rate->teams.push_back(i); 223 if (head == NULL || fr < head->rank) { 224 rate->next = head; 225 head = rate; 226 continue; 227 } else if (fr == head->rank) { 228 int t1 = rank1[i] > 0 ? rank1[i] :rank2[i]; 229 int t2 = rank1[head->teams.front()] > 0 ?rank1[head->teams.front()] : rank2[head->teams.front()]; 230 if (t1 == t2) { 231 head->teams.push_back(i); 232 continue; 233 } else if (t1 < t2) { 234 rate->next = head; 235 head = rate; 236 continue; 237 } 238 } 239 Rate * q = p->next; 240 bool f = false; 241 while(q != NULL) { 242 if (fr < q->rank) { 243 rate->next = q; 244 p->next = rate; 245 f = true; 246 break; 247 } else if (fr == q->rank) { 248 int t1 = rank1[i] > 0 ? rank1[i] :rank2[i]; 249 int t2 = rank1[q->teams.front()] > 0 ?rank1[q->teams.front()] : rank2[q->teams.front()]; 250 if (t1 == t2) { 251 q->teams.push_back(i); 252 } else if (t1 < t2) { 253 rate->next = q; 254 p->next = rate; 255 } else { 256 if (q->next == NULL) { 257 rate->next = q->next; 258 q->next = rate; 259 } else{ 260 int t3 = rank1[q->next->teams.front()] > 0 ? rank1[q->next->teams.front()] : rank2[q->next->teams.front()]; 261 if (t3 > t1) { 262 rate->next = q->next; 263 q->next = rate; 264 } else { 265 p = p->next; 266 q = q->next; 267 continue; 268 } 269 } 270 } 271 f = true; 272 break; 273 } 274 p = p->next; 275 q = q->next; 276 } 277 if (f == true) { 278 continue; 279 } 280 rate->next = NULL; 281 p->next = rate; 282 } 283 } 284 void output() { 285 for (Rate * p = head; p != NULL; p = p->next) { 286 p->teams.sort(); 287 for (list<int>::iterator it = p->teams.begin(); it != p->teams.end(); ++it) { 288 if (*it != p->teams.back()) { 289 cout << *it << " "; 290 } else { 291 cout << *it; 292 if (p->next != NULL) { 293 cout << endl; 294 } 295 } 296 } 297 } 298 } 299 int main () { 300 readData(); 301 cc2(); 302 sortRank(); 303 cc1(); 304 insertcc1(); 305 output(); 306 system("pause"); 307 return 0; 308 }
必须承认代码写得很拙劣,不过思路还是能看得比较清晰吧。