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. 長壽香菸
  18. 萬寶路香菸
  19. Dunhill 香菸
  20. 七星香菸
  21. 狗
  22. 鳥
  23. 貓
  24. 馬
  25. 魚

輸入

無

無

輸出

輸出的特定格式:
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;
}