Test Message

d527: 程式設計師的面試問題(三)

內容

在一條街上有五棟不同顏色的房子由左而右是第 1 棟到第 5 棟,
各住著不同國籍的人,各喝不同的飲料,各抽不同牌子的菸,各養不同的寵物,
給你線索和人事物的編號,請以特定格式輸出符合所有線索的所有可能。

線索:

  1. 英國人住在紅色的房子。
  2. 瑞典人養狗。
  3. 丹麥人喝茶。
  4. 綠色房子在白色房子的左邊。
  5. 綠色房子的主人喝咖啡。
  6. 抽寶馬香菸的人養鳥。
  7. 黃色房子的主人抽七星香菸。
  8. 中間那棟房子(第 3 棟)的主人喝牛奶。
  9. 挪威人住在第 1 棟房子。
  10. 抽長壽香菸的人住在養貓的人的隔壁。
  11. 養馬的人住在抽七星香菸的人的隔壁。
  12. 抽萬寶路香菸的人喝啤酒。
  13. 德國人抽 Dunhill 香菸。
  14. 挪威人住在藍色房子的隔壁。
  15. 抽長壽香菸的人有一個喝水的鄰居。

數字編號:

  1. 紅色房子
  2. 綠色房子
  3. 白色房子
  4. 黃色房子
  5. 藍色房子
  6. 英國人
  7. 瑞典人
  8. 丹麥人
  9. 挪威人
  10. 德國人
  11. 咖啡
  12. 牛奶
  13. 啤酒
  14. 寶馬香菸
  15. 長壽香菸
  16. 萬寶路香菸
  17. Dunhill 香菸
  18. 七星香菸

輸入

輸出

輸出的特定格式:
House Color Nation Drink Cigarette Pet
H1 <填數字> 9 <填數字> <填數字> <填數字>
H2 <填數字> <填數字> <填數字> <填數字> <填數字>
H3 <填數字> <填數字> <填數字> <填數字> <填數字>
H4 <填數字> <填數字> <填數字> <填數字> <填數字>
H5 <填數字> <填數字> <填數字> <填數字> <填數字>

以上述格式輸出,標頭要輸出,每一欄位為 10 個字元(包含標頭),靠右對齊。
<填數字>代表要配合線索求出該填的數字編號。
比如 9.挪威人住在第 1 棟,所以我已經把 Nation 對應到 H1(第 1 棟房子)的欄位填上 9(挪威人)。
請你完成這個表格,且要輸出符合所有線索並且可以完成這個表格的所有可能。
輸出並不包含空白行,連標頭一直輸出即可。


解題思路

DFS 窮舉所有可能,並按照題意進行剪枝。

本題困難點在於窮舉,因為要在窮舉所有物品的遞迴中再窮舉共 5 次房子的排列組合,而且又要保留進度,所以必須要用 5 個迴圈來窮舉房子的排列組合,具體方法見下方程式碼。


完整程式碼

AC (2ms, 80KB)
#include <stdio.h>
#define Color 0
#define Nation 1
#define Drink 2
#define Cigar 3
#define Pet 4

int house[7][5], isUse[7][5];

char dfs(int obj)
{
if (obj == 1)
{
for (int i = 1; i <= 5; i++)
{
if ((house[i][Color] == 2 && house[i + 1][Color] != 3))
return 0;
}
}
if (obj == 2)
{
for (int i = 1; i <= 5; i++)
{
if ((house[1][Nation] != 9) || (house[i][Nation] == 6 && house[i][Color] != 1) ||
(house[i][Nation] == 9 && !(house[i - 1][Color] == 5 || house[i + 1][Color] == 5)))
return 0;
}
}
else if (obj == 3)
{
for (int i = 1; i <= 5; i++)
{
if ((house[3][Drink] != 13) || (house[i][Nation] == 8 && house[i][Drink] != 11) ||
(house[i][Color] == 2 && house[i][Drink] != 12))
return 0;
}
}
else if (obj == 4)
{
for (int i = 1; i <= 5; i++)
{
if ((house[i][Color] == 4 && house[i][Cigar] != 20) || (house[i][Cigar] == 18 && house[i][Drink] != 14) ||
(house[i][Nation] == 10 && house[i][Cigar] != 19) || (house[i][Cigar] == 17 && !(house[i - 1][Drink] == 15 || house[i + 1][Drink] == 15)))
return 0;
}
}
else if (obj == 5)
{
for (int i = 1; i <= 5; i++)
{
if ((house[i][Nation] == 7 && house[i][Pet] != 21) || (house[i][Cigar] == 16 && house[i][Pet] != 22) ||
(house[i][Cigar] == 17 && !(house[i - 1][Pet] == 23 || house[i + 1][Pet] == 23)) ||
(house[i][Pet] == 24 && !(house[i - 1][Cigar] == 20 || house[i + 1][Cigar] == 20)))
return 0;
}
return 1;
}
const int ft = obj * 5;
char isUse[7] = { 0 };
for (int t1 = 1; t1 <= 5; t1++)
{
house[1][obj] = ft + t1;
isUse[t1] = 1;
for (int t2 = 1; t2 <= 5; t2++)
{
if (isUse[t2]) continue;
house[2][obj] = ft + t2;
isUse[t2] = 1;
for (int t3 = 1; t3 <= 5; t3++)
{
if (isUse[t3]) continue;
house[3][obj] = ft + t3;
isUse[t3] = 1;
for (int t4 = 1; t4 <= 5; t4++)
{
if (isUse[t4]) continue;
house[4][obj] = ft + t4;
isUse[t4] = 1;
for (int t5 = 1; t5 <= 5; t5++)
{
if (isUse[t5]) continue;
house[5][obj] = ft + t5;
if (dfs(obj + 1))
return 1;
break;
}
isUse[t4] = 0;
}
isUse[t3] = 0;
}
isUse[t2] = 0;
}
isUse[t1] = 0;
}
return 0;
}

int main()
{
dfs(0);
printf(" House Color Nation Drink Cigarette Pet\n");
printf(" H1% 10d% 10d% 10d% 10d% 10d\n", house[1][0], house[1][1], house[1][2], house[1][3], house[1][4]);
printf(" H2% 10d% 10d% 10d% 10d% 10d\n", house[2][0], house[2][1], house[2][2], house[2][3], house[2][4]);
printf(" H3% 10d% 10d% 10d% 10d% 10d\n", house[3][0], house[3][1], house[3][2], house[3][3], house[3][4]);
printf(" H4% 10d% 10d% 10d% 10d% 10d\n", house[4][0], house[4][1], house[4][2], house[4][3], house[4][4]);
printf(" H5% 10d% 10d% 10d% 10d% 10d\n", house[5][0], house[5][1], house[5][2], house[5][3], house[5][4]);
return 0;
}