Daily practice: day 11 - detective reasoning

Detective reasoning

Title Description
Mingming recently fell in love with the detective cartoon Conan and indulged in the reasoning game, so he called a group of students to play the reasoning game. The content of the game is like this. Mingming's classmates first discuss that one of them should act as a criminal (without knowing it). Mingming's task is to find out the criminal. Then, clearly ask each student one by one, and the respondent may say:

Content of testimony:
I am guilty.
I am not guilty.
XXX is guilty.
XXX is not guilty.
Today is XXX
Meaning of testimony:
I'm a criminal
I'm not a criminal
xxx is a criminal (xxx means the name of a classmate)
xxx is not a criminal
Today is xxx (xxx means the day of the week, which is one of the Monday Tuesday Wednesday fnay Saturday)  

Other words appearing in the testimony are not included in the content of logical reasoning. What Mingming knows is that N of his classmates always tell lies, and the rest always tell the truth. Now, Mingming needs your help to infer who is the real murderer from his classmates' words. Please remember, there is only one murderer!

Enter description
Enter several lines.
The first line has three integers, m (1 ≤ m ≤ 20), N (1 ≤ N ≤ m) and P (1 ≤ P ≤ 100); M is the number of obvious students participating in the game, N is the number of people who always lie, and P is the total number of testimony.
Next M lines, each line is the name of a classmate (composed of English letters, no nominative case, all capitalized).
There are P lines in the future. Each line starts with the name of a classmate, followed by a colon and a space, followed by a testimony, which conforms to the format listed in the previous table. The testimony will not exceed 250 characters per line.
There are no two consecutive spaces in the input, and there are no spaces at the beginning and end of each line.

Output description
If your program can determine who is the criminal, output his name; If the program judges that more than one person may be a criminal, it outputs Cannot Determine; If the program determines that no one may become a criminal, it outputs Impossible.

Input and output samples
input
3 1 5
MIKE
CHARLES
KATE
MIKE: I am guilty.
MIKE: Today is Sunday.
CHARLES: MIKE is guilty.
KATE: I am guilty.
KATE: How are you??
output
MIKE

Operating limits
Maximum running time: 1s
Maximum operating memory: 128M

/*
Large scale simulation problem
*/

#include <bits/stdc++.h>
using namespace std;

//m: Total number n: number of people who always lie p: total number of people who speak
int m, n,  p;
//judge[i]: is the I sentence true or false, true 1 false - 1 unclear 0 w[i]: the I game is said by the person with the number
int judge[21], w[200];
//err: contradiction mark nx: current possible criminals
int err,  nx;
//name[i]: everyone's name (No. 1~m) say[i]: everyone's words day[i]: all day of the week names
string name[100], say[200];
string day[10] = {"0", "Today is Sunday.", "Today is Monday.",
                  "Today is Tuesday.", "Today is Wednesday.", "Today is Thursday.",
                  "Today is Friday.", "Today is Saturday.",
                 };

//The set function marks whether a person speaks true or false
void sset(int who, int x) {
	if (judge[who] == -x)
		err = 1; //If a person tells the truth and lies, there is a contradiction
	else
		judge[who] = x;
}

int main() {
	cin >> m >> n >> p;
	for (int i = 1; i <= m; i++) {
		cin >> name[i];
	}
	for (int i = 1; i <= p; i++) {
		string nm;
		cin >> nm; //Enter the name of the person who said this
		nm.erase(nm.end() - 1); //Delete the colon in nm to judge the number of this sentence
		for (int j = 1; j <= m; j++) {
			if (name[j] == nm)
				w[i] = j;
		}
		getline(cin, say[i]);
		say[i].erase(say[i].begin()); //Delete the starting space in say[i]
	}

	for (int td = 1; td <= 7; td++) { //What day is it today
		for (int px = 1; px <= m; px++) { //What's the serial number of the violent criminal
			err = 0; //Clear mark
			memset(judge, 0, sizeof(judge)); //Initialize to unclear true or false
			//Judge each sentence in turn
			for (int i = 1; i <= p; i++) {
				int who = w[i]; //The number of the person who said this
				//If a person is a criminal and says he is a criminal, he is telling the truth, otherwise he is lying
				if (say[i] == "I am guilty.")
					sset(who, px == who ? 1 : -1);
				//If a person is not a criminal and says he is not a criminal, he is telling the truth, otherwise he is lying
				if (say[i] == "I am not guilty.")
					sset(who, px != who ? 1 : -1);
				//If a person says today is the day of the week, if he is right, he is true, and if he is wrong, he is false
				for (int j = 1; j <= 7; j++) {
					if (say[i] == day[j])
						sset(who, j == td ? 1 : -1);
				}
				//If a person says that others are not criminals, if he is right, he is true, and if he is wrong, he is false
				for (int j = 1; j <= m; j++) {
					if (say[i] == name[j] + " is guilty.")
						sset(who, j == px ? 1 : -1);
					if (say[i] == name[j] + " is not guilty.")
						sset(who, j != px ? 1 : -1);
				}
			}
			int cnt = 0; //Number of liars
			int no = 0; //The number of people who don't know whether it's true or not
			for (int i = 1; i <= m; i++) {
				if (judge[i] == -1) //false
					cnt++;
				if (judge[i] == 0) //unclear
					no++;
			}
			//In case of impossibility, err = 1, contradiction occurs
			//If CNT < = n < = cnt + no, the assumption is reasonable
			if (!err && cnt <= n && cnt + no >= n) {
				if (nx && nx != px) { //If there are two reasonable criminals
					cout << "Cannot Determine";
					return 0;
				} else {
					nx = px;
				}
			}
		}
	}
	if (!nx)
		cout << "Impossible";
	else
		cout << name[nx];

	return 0;
}

Tags: C C++ Algorithm leetcode Programmer

Posted on Tue, 30 Nov 2021 09:09:46 -0500 by webtuto