Test Message

b265: Q11286 - Conformity

內容

Waterloo 大學的新鮮人由於興趣不同,對於課程的選擇不盡相同,而校方希望他們所選的課程儘量一致,所以設立了一個獎項,頒發給 選擇的「課程組合」為「最受歡迎的課程組合」的學生。


輸入

輸入有多組測試資料,每組資料的開頭有一個整數 n 表示新生的人數( 1 <= n <= 10000 ),接下來有 n 列分別為這些新生所選擇的課程代號,每列有 5 個表示課程代號的整數,其值介於 100 ~ 499。當 n = 0 表示測試資料結束。

3
100 101 102 103 488
100 200 300 101 102
103 102 101 488 100
3
200 202 204 206 208
123 234 345 456 321
100 200 300 400 444
0

輸出

一組課程的受歡迎程度視所有剛好選擇該組課程的學生人數而定,如果沒有其他「課程組合」的人數比此「課程組合」的人數高,則該課程為最 受歡迎的「課程組合」,請對每組測試資料輸出選擇最受歡迎的「課程組合」的人數。

2
3


解題思路

解題方向 :

  1. 由於”選課順序”不影響”課程組合”,所以先將輸入的選課排序好避免因不同的”選課順序”被視為不同的”課程組合”。

  2. 將排序好的課程組合打成一個雜湊值(Hash)。

  3. 查看雜湊表的 Hash,如果已經有 Hash 存過得到的雜湊值,則該 Hash 的 Count+1,反之則新增一個 Key 為得到的雜湊值的 Hash,並將該 Hash 新增至雜湊表。 (這段的 Hash 指的是 struct Hash)

  4. 輸入完全部課程組合後,再完整的遍歷一次雜湊表即可取得 “最受歡迎的課程組合”的總修課人數。

一些注意事項 :

  • 雜湊表大小設為 2 的次方數,這樣可以在存雜湊值進去時用 & 取代 % 來加速。
  • 因為有多組輸入,所以每次計算完都要清空一次雜湊表。
  • “最受歡迎的課程組合”可以是複數堂,也就是說,當”最受歡迎的課程組合”人數為 3,且有 3 堂修課人數為 3 的課程組合時,答案應該是 3(堂) * 3(人) = 9 人。
  • 雜湊運算並不是安全的判斷方式,因為可能會產生雜湊碰撞(兩不同的資料得到一樣的雜湊資),但由於發生機率過低,所以這裡無視這個問題。

完整程式碼

AC (62ms, 344KB)
#include <stdio.h>
#include <stdlib.h>

typedef struct Hash
{
unsigned int Key;
int Count;
struct Hash* Next;
}Hash;

Hash HashTable[1024];
unsigned int list[5];
int n;

int cmp(const unsigned int* lhs, const unsigned int* rhs)
{
return *lhs - *rhs;
}

inline unsigned int toHash(unsigned int src[])
{
return (src[0] << 28) + (src[1] << 21) + (src[2] << 14) + (src[3] << 7) + src[4];
}

inline void AddHash(unsigned int hash)
{
Hash* now = &HashTable[hash & 1023];
while (now->Key != hash)
{
if (now->Next == NULL)
{
now = now->Next = malloc(sizeof(Hash));
now->Key = hash;
now->Next = NULL;
now->Count = 1;
return;
}
now = now->Next;
}
now->Count++;
}

int PopularityCount()
{
int max = 0, count = 0;
Hash* now, * tmp;
for (int i = 0; i < 1024; i++)
{
if (HashTable[i].Next != NULL)
{
now = HashTable[i].Next;
do
{
if (max <= now->Count)
{
if (max == now->Count)
count += max;
else
count = max = now->Count;
}
tmp = now;
now = now->Next;
free(tmp);
} while (now != NULL);
HashTable[i].Next = NULL;
}
}
return count;
}

int main()
{
while (scanf(" %d", &n) == 1 && n)
{
for (int i = 0; i < n; i++)
{
scanf(" %u %u %u %u %u", &list[0], &list[1], &list[2], &list[3], &list[4]);
qsort(list, 5, sizeof(unsigned int), cmp);
AddHash(toHash(list));
}
printf("%d\n", PopularityCount());
}
return 0;
}