POJ 1478

Island of Logic
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 555 Accepted: 169

Description

The Island of Logic has three kinds of inhabitants: divine beings that always tell the truth, evil beings that always lie, and human beings that are truthful during the day and lie at night. Every inhabitant recognizes the type of every other inhabitant. 
A social scientist wants to visit the island. Because he is not able to distinguish the three kinds of beings only from their looks, he asks you to provide a communication analyzer that deduces facts from conversations among inhabitants. The interesting facts are whether it is day or night and what kind of beings the speakers are. 

Input

The input contains several descriptions of conversations. Each description starts with an integer n, the number of statements in the conversation. The following n lines each contain one statement by an inhabitant. Every statement line begins with the speaker's name, one of the capital letters A, B, C, D, E, followed by a colon `:'. Next is one of the following kinds of statements: 

I am [not] ( divine | human | evil | lying ). 

X is [not] ( divine | human | evil | lying ). 

It is ( day | night ). 

Square brackets [] mean that the word in the brackets may or may not appear, round brackets () mean that exactly one of the alternatives separated by | must appear. X stands for some name from A, B, C, D, E. There will be no two consecutive spaces in any statement line, and at most 50 statements in a conversation. 

The input is terminated by a test case starting with n = 0. 

Output

For each conversation, first output the number of the conversation in the format shown in the sample output. Then print ``This is impossible.'', if the conversation cannot happen according to the rules or ``No facts are deducible.'', if no facts can be deduced. Otherwise print all the facts that can be deduced. Deduced facts should be printed using the following formats: 

X is ( divine | human | evil ). 

It is ( day | night ). 

X is to be replaced by a capital letter speaker name. Facts about inhabitants must be given first (in alphabetical order), then it may be stated whether it is day or night. 

The output for each conversation must be followed by a single blank line. 

Sample Input

1
A: I am divine.
1
A: I am lying.
1
A: I am evil.
3
A: B is human.
B: A is evil.
A: B is evil.
0

Sample Output

Conversation #1
No facts are deducible.

Conversation #2
This is impossible.

Conversation #3
A is human.
It is night.

Conversation #4
A is evil.
B is divine.

Hint

To make things clearer, we will show the reasoning behind the third input example, where A says ``I am evil.''. What can be deduced from this? Obviously A cannot be divine, since she would be lying, similarly A cannot be evil, since she would tell the truth. Therefore, A must be human, moreover, since she is lying, it must be night. So the correct output is as shown. 

In the fourth input example, it is obvious that A is lying since her two statements are contradictory. So, B can be neither human nor evil, and consequently must be divine. B always tells the truth, thus A must be evil. Voila!

Source


题意:

有五个人a, b, c, d, e, 每个人可能是天使,恶魔或者普通人中的一种。现在有白天和夜晚两种情况, 天使始终说实话,恶魔始终说假话,普通人在白天说真话,在夜晚说假话。现在给出一些人说的话,要求通过这些话判断出一些人的身份,或者推出矛盾。


思路:考虑人数较少,可以暴力枚举每个人的身份以及白天还是黑夜,根据语句判断是否有矛盾,最后得到所有可能的身份情况,再判断每个人的身份是否有多重情况或着是否不可能有合理的身份,从而得到答案。总复杂度O(2*3^5*n)(n为语句的数目)


此题麻烦之处在于条件很多,判断每个枚举的状态是否合法或矛盾很复杂,但只要逻辑清楚,剩下的都是码农工作.


代码:

JAVA写的......将就看看吧

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
	Statement stm[] = new Statement[500];
	final int divine = 0, human = 1, evil = 2, lying = 3, day = 4, night = 5;
	int[] state_type = new int[10];
	int[][] state = new int[10][10];
	int n;

	public static void main(String[] arg) {
		new Main().run();
	}

	public void run() {
		
		for (int i = 0; i < 500; i++)
			stm[i] = new Statement();
		Scanner in = new Scanner(System.in);
		int cas = 0;
		while (true) {
			for(int i = 0; i < 6; i++)
				for(int j = 0; j < 6; j++)
					state[i][j] = 0;
			n = in.nextInt();
			if (n == 0)
			{
				in.close();
				return;
			}
				
			String line = in.nextLine();
			for (int i = 0; i < n; i++) {
				line = in.nextLine();
				//System.out.println("<<<<<"+line);
				String[] spli = line.split(" ");
				stm[i].u = stm[i].v = spli[0].charAt(0) - 'A';
				stm[i].no = false;
				if (spli[1].equals("It")) {
					//System.out.println("spli2: "+spli[3]);
					stm[i].type = spli[3].equals("day.") ? day : night;
				} else if (spli[1].equals("I")) {
					int temp = 0;
					if (spli[3].equals("not")) {
						stm[i].no = true;
						temp = 1;
					}
					if (spli[temp + 3].equals("divine.")) {
						stm[i].type = divine;
					} else if (spli[temp + 3].equals("human.")) {
						stm[i].type = human;
					} else if (spli[temp + 3].equals("lying.")) {
						stm[i].type = lying;
					} else
						stm[i].type = evil;
				} else {
					stm[i].u = spli[0].charAt(0) - 'A';
					stm[i].v = spli[1].charAt(0) - 'A';
					int temp = 0;
					if (spli[3].equals("not")) {
						stm[i].no = true;
						temp = 1;
					}
					if (spli[temp + 3].equals("divine.")) {
						stm[i].type = divine;
					} else if (spli[temp + 3].equals("human.")) {
						stm[i].type = human;
					} else if (spli[temp + 3].equals("lying.")) {
						stm[i].type = lying;
					} else
						stm[i].type = evil;
				}
				//System.out.printf(">>>>>> %d %d %b %d\n", stm[i].u, stm[i].v, stm[i].no, stm[i].type);

			}
			deal();
			if(cas != 0)
				System.out.println();
			System.out.printf("Conversation #%d\n",++cas);
			
			printAnswer();
			
		}
	}

	private void printAnswer() {
		// TODO Auto-generated method stub
		ArrayList<String> ans = new ArrayList<String>();
		boolean flag = true;
		for(int i = 0; i < 6; i++)
		{
			int cnt = 0, type = 0;
			for(int j = 0; j < 6; j++)
			{
				if(state[i][j] == 1)
				{
					cnt++;
					type = j;
				}
				
			}
			//System.out.println("i: "+i+" "+cnt);
			if(i == 5)
			{
				//System.out.println("day_night: "+cnt);
			}
			if(cnt == 0)
			{
				System.out.println("This is impossible.");
				return;
			}
			else if(cnt == 1)
			{
				flag = false;
				String str = "";
				if(i != 5)
				{
					str += (char)(i+'A');
					str += " is ";
					if(type == divine) str += "divine.";
					else if(type == human) str += "human.";
					else str += "evil.";
				}
				else
				{
					str += "It is ";
					if(type == day) str += "day.";
					else str += "night.";
				}
				ans.add(str);
			}
			
		}
		if(flag)
		{
			System.out.println("No facts are deducible.");
			return;
		}
		//Collections.sort(ans, new Cmp());
		//ans.sort(new Cmp());
		
		for(int i = 0; i < ans.size(); i++)
		{
			System.out.println(ans.get(i));
		}
	}

	void deal() {
		for (int i = 0; i < 3; i++) {
			state_type[0] = i;
			for (int j = 0; j < 3; j++) {
				state_type[1] = j;
				for (int k = 0; k < 3; k++) {
					state_type[2] = k;
					for (int l = 0; l < 3; l++) {
						state_type[3] = l;
						for (int m = 0; m < 3; m++) {
							state_type[4] = m;
							for (int f = 4; f < 6; f++) {
								state_type[5] = f;
								make_state();
							}
						}
					}
				}
			}
		}
	}

	void make_state() {
		boolean flag = true;
		
		for (int i = 0; i < n; i++) {
			int u = stm[i].u, v = stm[i].v;

			int type = stm[i].type;
			boolean no = stm[i].no;

			if (type == day || type == night) {
				if (state_type[u] == divine && state_type[5] != type) {
					flag = false;
					break;
				}
				if (state_type[u] == evil && state_type[5] == type) {
					flag = false;
					break;
				}
				if (state_type[u] == human && type == night) {
					flag = false;
					break;
				}
			} else if (sayTrue(state_type[u], state_type[5])) {
				if(no)
				{
					if(type == lying)
					{
						if(!sayTrue(state_type[v], state_type[5]))
						{
							flag = false;
							break;
						}
					}
					else if (state_type[v] == type) {
						flag = false;
						break;
					}
				}
				else
				{
					if(type == lying)
					{
						if(sayTrue(state_type[v], state_type[5]))
						{
							flag = false;
							break;
						}
					}
					else if (state_type[v] != type) {
						flag = false;
						break;
					}
				}
			} else {
				if(no)
				{
					if(type == lying)
					{
						if(sayTrue(state_type[v], state_type[5]))
						{
							flag = false;
							break;
						}
					}
					else if (state_type[v] != type) {
						flag = false;
						break;
					}
				}
				else
				{
					if(type == lying)
					{
						if(!sayTrue(state_type[v], state_type[5]))
						{
							flag = false;
							break;
						}
					}
					else if (state_type[v] == type) {
						flag = false;
						break;
					}
				}
			}
		}

		if(flag)
		{
			//System.out.println(">>>>>>>>>>>>>>>>>> "+state_type[5]);
			for(int i = 0; i < 6; i++)
			{
				state[i][state_type[i]] = 1;
			}
		}
	}

	boolean sayTrue(int type, int day_night)
	{
		if(type == divine || (type == human && day_night == day)) return true;
		return false;
	}
}

class Statement {
	public int u, v, type;
	public boolean no;

	public Statement() {
		u = v = type = -1;
		no = false;
	}
};
class Cmp implements Comparator
{

	public int compare(Object arg0, Object arg1) {
		// TODO Auto-generated method stub
		String a = (String) arg0, b = (String) arg1;
		return a.compareTo(b);
		
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值