題目:熟悉的故事。。。有一個島上面,有三種生物,神、人、魔,神永遠說真話,魔永遠說假話,
人白天說真話、晚上說假話;現在有一些生物和他們說的話,判斷他們的物種和時間。
分析:圖論,搜索。每句話的格式為speaker : subject be [not] object;
这里判断分为两步,①句子的真值、②说话人和句子真值的匹配情况;
最多有五個人A、B、C、D、E,每人有3中種選擇(神、人、魔),時間可能有兩種(日、夜);
這裡數據最多有3^5*2,很小,所以直接枚舉(dfs),然後定義一個判定是否合法的函數即可;
题目描述的有點不清楚(可能是我沒看明白╮(╯▽╰)╭),物種或者時間,有一個能確定就可以;
如果有一個出現的生物只能為唯一物種或時間只能是日夜中的一種時,則未確定輸出;
如果每一個出現的生物都可以是多種物種並且時間可以是日夜中的任何一種,則不確定;
如果沒有找到任何可能,則不存在解;
說明:注意輸出格式,每組數據后有換行(尤其是時間)。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
char speaker[55], map[99];
string subject[55], nots[55], object[55], value[99], save[99][3], days[3], buf;
string type[3] = {"divine.", "human.", "evil."};
int test(int n, int night)
{
string day = ((night)?("night."):("day."));
int truevalue = true;
for (int i = 0; i < n; ++ i) {
//判断句子的真伪
if (object[i] == "day." || object[i] == "night.")
truevalue = (day == object[i]);
else {
char Index = (subject[i][0]=='I')?(speaker[i]):(subject[i][0]);
if (object[i] == "lying.")
truevalue = (value[Index] == "human." && night) || (value[Index] == "evil.");
else truevalue = (value[Index] == object[i]);
}
if (nots[i] == "not") truevalue = !truevalue;
//判断说话人的角色和句子真伪关系
if (value[speaker[i]] == "divine." && !truevalue)
return false;
if (value[speaker[i]] == "evil." && truevalue)
return false;
if (value[speaker[i]] == "human." && night == truevalue)
return false;
}
//记录数据
for (char c = 'A' ; c <= 'E'; ++ c) {
if (!map[c]) continue;
if (value[c] == "divine.")
save[c][0] = value[c];
if (value[c] == "evil.")
save[c][1] = value[c];
if (value[c] == "human.")
save[c][2] = value[c];
}
days[night] = day;
return true;
}
void dfs(char c, int n)
{
while (c <= 'E' && !map[c]) c ++;
if (c > 'E') {
test(n, 0);
test(n, 1);
return;
}
for (int i = 0; i < 3; ++ i) {
value[c] = type[i];
dfs(c+1, n);
}
}
int main()
{
int line, cases = 1;
while (cin >> line && line) {
days[0] = days[1] = "";
for (char c = 'A'; c <= 'E'; ++ c) {
map[c] = false;
save[c][0] = save[c][1] = save[c][2] = "";
}
for (int i = 0; i < line; ++ i) {
cin >> speaker[i] >> buf >> subject[i] >> buf >> nots[i];
if (nots[i] == "not")
cin >> object[i];
else object[i] = nots[i];
map[speaker[i]] = true;
if (subject[i][0] != 'I')
map[subject[i][0]] = true;
}
dfs('A', line);
cout << "Conversation #" << cases ++ << endl;
int sure = 0, sum = 0;
for (char c = 'A'; c <= 'E'; ++ c) {
int count = 3;
for (int i = 0; i < 3; ++ i)
count -= (save[c][i] == "");
for (int i = 0; i < 3; ++ i)
if (count == 1 && save[c][i] != "") {
cout << c << " is " << save[c][i] << endl;
sure ++;//记录能确定的人数
}
if (count > 0) sum ++;//记录可能存在的解
}
if ((days[0] == "" || days[1] == "") && (days[0] != "" || days[1] != "")) {
sure ++;
sum ++;
cout << "It is " << (days[0]==""?days[1]:days[0]) << endl;
}
if (!sum) cout << "This is impossible." << endl;
else if (!sure) cout << "No facts are deducible." << endl;
cout << endl;
}
return 0;
}
測試數據:
6
A: B is human.
A: B is evil.
B: A is human.
C: A is not lying.
B: C is not human.
D: E is not lying.
4
A: I am human.
A: It is night.
B: I am human.
B: It is day.
3
A: I am human.
B: I am human.
A: B is lying.
3
A: I am divine.
B: A is not lying.
A: B is lying.
3
A: I am divine.
B: A is lying.
A: B is lying.
5
A: B is human.
A: B is evil.
B: A is evil.
C: A is not lying.
B: It is day.
5
C: A is not lying.
A: B is human.
A: B is evil.
B: A is evil.
B: It is day.
1
A: A is not lying.
1
A: A is lying.
2
E: E is evil.
E: E is divine.
7
A: It is night.
B: It is day.
C: I am human.
E: C is human.
C: E is divine.
A: B is lying.
B: C is evil.