它是可以解決的。使用m == 26
和n == 20
它將需要大約100 MB的空間和〜1秒的時間。 下面是解決方案,我剛纔在C#實現的(它會成功編譯的C++和Java也將需要只是一些小的改動):
int[] GetAssignments(int[] studentsPerLetter, int[] rooms)
{
int numberOfRooms = rooms.Length;
int numberOfLetters = studentsPerLetter.Length;
int roomSets = 1 << numberOfRooms; // 2^(number of rooms)
int[,] map = new int[numberOfLetters + 1, roomSets];
for (int i = 0; i <= numberOfLetters; i++)
for (int j = 0; j < roomSets; j++)
map[i, j] = -2;
map[0, 0] = -1; // starting condition
for (int i = 0; i < numberOfLetters; i++)
for (int j = 0; j < roomSets; j++)
if (map[i, j] > -2)
{
for (int k = 0; k < numberOfRooms; k++)
if ((j & (1 << k)) == 0)
{
// this room is empty yet.
int roomCapacity = rooms[k];
int t = i;
for (; t < numberOfLetters && roomCapacity >= studentsPerLetter[t]; t++)
roomCapacity -= studentsPerLetter[t];
// marking next state as good, also specifying index of just occupied room
// - it will help to construct solution backwards.
map[t, j | (1 << k)] = k;
}
}
// Constructing solution.
int[] res = new int[numberOfLetters];
int lastIndex = numberOfLetters - 1;
for (int j = 0; j < roomSets; j++)
{
int roomMask = j;
while (map[lastIndex + 1, roomMask] > -1)
{
int lastRoom = map[lastIndex + 1, roomMask];
int roomCapacity = rooms[lastRoom];
for (; lastIndex >= 0 && roomCapacity >= studentsPerLetter[lastIndex]; lastIndex--)
{
res[lastIndex] = lastRoom;
roomCapacity -= studentsPerLetter[lastIndex];
}
roomMask ^= 1 << lastRoom; // Remove last room from set.
j = roomSets; // Over outer loop.
}
}
return lastIndex > -1 ? null : res;
}
來自實例OP問題:
int[] studentsPerLetter = { 25, 150, 200, 50 };
int[] rooms = { 350, 50, 50 };
int[] ans = GetAssignments(studentsPerLetter, rooms);
答案是:
2
0
0
1
指示的空間爲每個學生的姓氏字母索引。如果分配不可行,我的解決方案將返回null
。
[編輯]
經過千自動生成的測試我的朋友已經發現,在代碼向後構建解決方案的錯誤。它不會影響主算法,因此修復這個錯誤將是對讀者的一個練習。
揭示該錯誤的測試用例是students = [13,75,21,49,3,12,27,7]
和rooms = [6,82,89,6,56]
。我的解決方案沒有回答,但實際上有一個答案。請注意,解決方案的第一部分正常工作,但回答構造部分失敗。
你能把在兩個不同房間裏的姓氏以同一個字符開頭的學生分開嗎? – Bill 2013-05-04 17:34:33
@比爾 - 爲了這個問題,我們說不。從邏輯上講,如果我們爲同一封信提供多個房間,並且每個人都只顯示其中一個,那將是非常糟糕的。 – templatetypedef 2013-05-04 17:38:44
你不需要拆分一個字母。 – starblue 2013-05-04 17:38:59