UVa 592 - Island of Logic

題目:熟悉的故事。。。有一個島上面,有三種生物,神、人、魔,神永遠說真話,魔永遠說假話,

            人白天說真話、晚上說假話;現在有一些生物和他們說的話,判斷他們的物種和時間。

分析:圖論,搜索。每句話的格式為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.



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值