UVA 592 - Island of Logic
来源:互联网 发布:借尸还魂事件 知乎 编辑:程序博客网 时间:2024/05/17 06:22
时间限制:3.000秒
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=533&mosmsg=Submission+received+with+ID+14904418
这种题,说难吧不难,但是就是不好做,因为太麻烦,比较练代码能力。
大意是一座岛上有三个种族,神族(divine)永远讲实话,魔鬼(evil)永远在撒谎,而人类(human)比较特殊,白天(day)讲实话晚上(night)撒谎。
输入是多组的,每组都是一些人的陈述,开头会先指出是谁说的,然后跟一个冒号":",然后是他(她,它)说的句子,这些句子都符合如下的格式中的一种:
I am [not] ( divine | human | evil | lying ).X is [not] ( divine | human | evil | lying ).It is ( day | night ).方括号[]里的内容是可能出现也可能不出现的,当然,意思也不相同。而括号()里的内容则是一定有且只有一个词会在一条陈述中出现。讲话的人和第二句中被描述的X以字母代替,可以为ABCDE中的任意一个。
对于每组数据,要求你根据这些陈述判断说话的人和被描述的人的身份,给出能够确定的信息来,也就是说,可能给了5个人的身份你只能推出3个来,那么就把能确定身份的这3个人的信息输出出来。如果给出的描述自相矛盾无解,输出“This is impossible.”,如果给出的描述得不出任何确定的信息,输出“No facts are deducible.”,如果有人的身份是可以确定的,则按照如下格式表述这个人的身份:
X is ( divine | human | evil ).如果白天还是晚上是确定的,也要输出,格式为:
It is ( day | night ).具体可以参见样例。
解法比较简单,就是枚举所有可能的情况,挨个带进去检查就是了。但是实现起来就略麻烦了……纯练代码能力了吧。
废话少说,上代码。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#define yes 1#define no 0#define divine 0#define human 1#define evil 2#define free 0#define day 3#define night 4#define lying 5#define time -2using namespace std;struct information { // 定义每句话的结构体 int speaker, target, real, description; // 每句话的内容设定为讲话者、这句话形同的对象、be动词、描述};int Letter2Num(char match[], char l) { int i; for(i = 0; match[i] != '0' && match[i] != l && i != 5; ++i); return i;}int GetNum(char match[], string &in) { cin >> in; if(in[0] >= 'A' && in[0] <= 'E') { int i = Letter2Num(match, in[0]); match[i] = in[0]; return i; } else if(in == "I") return -1; else return time;}int GetDescription(string &in) { if(in == "divine.") return divine; else if(in == "human.") return human; else if(in == "evil.") return evil; else if(in == "day.") return day; else if(in == "night.") return night; else return lying;}void GetStatusAndDescription(information &info, char match[], string &in) { cin >> in; cin >> in; if(in == "not") { info.real = no; cin >> in; info.description = GetDescription(in); } else { info.real = yes; info.description = GetDescription(in); }}void GetInfo(information &info, char match[]) { string in; info.speaker = GetNum(match, in); info.target = GetNum(match, in); if(info.target == -1) info.target = info.speaker; GetStatusAndDescription(info, match, in);}void PutInfo(char match[], const information &info) { cout << match[info.speaker] << ": "; if(info.speaker == info.target) cout << "I am "; else if(info.target == time) cout << "It is "; else cout << match[info.target] << " is "; if(info.real == no) cout << "not "; switch(info.description) { case divine: cout << "divine."; break; case human: cout << "human."; break; case evil: cout << "evil."; break; case day: cout << "day."; break; case night: cout << "night."; break; case lying: cout << "lying"; break; }}string Identity(int ID) { switch(ID) { case divine: return "divine"; case human: return "human"; case evil: return "evil"; }}bool LastPossibility(int *s, int *e) { while(s != e) if(*(s++) != 2) return false; return true;}bool NextPossibility(int *s, int *e) { if(LastPossibility(s, e)) return false; for(int t = 1; s != e; ++s) { int temp = ((*s) + t) / 3; *s = ((*s) + t) % 3; t = temp; } return true;}int CalNum(char match[]) { int i; for(i = 5; i != 0 && match[i] == '0'; i--); return i + 1;}bool CheckInfo(const information &info, int p[], int m, int t) { bool ok; if(info.target == time) { if(info.description == t) ok = true; else ok = false; } else { if(info.description == lying) { switch(p[info.target]) { case divine: ok = false; break; case human: if(t == day) ok = false; else ok = true; break; case evil: ok = true; break; } } else { if(p[info.target] == info.description) ok = true; else ok = false; } } if(!info.real) ok = !ok; switch(p[info.speaker]) { case divine: break; case human: if(t == day); else ok = !ok; break; case evil: ok = !ok; break; } return ok;}bool HaveHuman(int *s, int *e) { while(s != e) if(*(s++) == human) return true; return false;}void CopyAns(int ans[], int p[], int vis[], int *m, int *dayornight, int resofdayortime, bool *first) { if(*first) { for(int i = 0; i != *m; ++i) ans[i] = p[i]; for(int i = 0; i != *m; ++i) vis[i] = 1; *dayornight = resofdayortime; *first = false; } else { for(int i = 0; i != *m; ++i) if(vis[i] && p[i] != ans[i]) vis[i] = 0; switch(*dayornight) { case day: if(resofdayortime != day) *dayornight = day + night; break; case night: if(resofdayortime != night) *dayornight = day + night; break; } }}bool CheckPossibilities(information info[], int *n, int p[], int ans[], int *m, int vis[], int *dayornight, bool *first) { bool checkday = true, checknight = true; for(int i = 0; i != *n; ++i) { if(checkday) checkday = CheckInfo(info[i], p, *m, day); if(checknight) checknight = CheckInfo(info[i], p, *m, night); if(!(checkday || checknight)) return false; } if(checkday && checknight) CopyAns(ans, p, vis, m, dayornight, day + night, first); else if(checkday) CopyAns(ans, p, vis, m, dayornight, day, first); else if(checknight) CopyAns(ans, p, vis, m, dayornight, night, first); return true;}struct Out { char match; int ans, vis; bool operator < (const Out& o) const { return match < o.match; }};int main() { int n, t = 0; char match[10]; while(cin >> n && n) { cout << "Conversation #" << ++t << endl; memset(match, '0', sizeof(match)); information info[n]; for(int i = 0; i != n; ++i) GetInfo(info[i], match); int m = CalNum(match); int p[m], ans[m], vis[m], dayornight = free; memset(vis, 0, sizeof(vis)); memset(p, 0, sizeof(p)); bool first = true; bool haveans = false; do { if(CheckPossibilities(info, &n, p, ans, &m, vis, &dayornight, &first)) { haveans = true; } } while(NextPossibility(p, p + m)); if(!haveans) cout << "This is impossible." << endl; else { Out o[m]; for(int i = 0; i != m; ++i) o[i].match = match[i], o[i].ans = ans[i], o[i].vis = vis[i]; sort(o, o + m); bool outans = false; for(int i = 0; i != m; ++i) if(o[i].vis) { outans = true; cout << o[i].match << " is " << Identity(o[i].ans) << "." << endl; } switch(dayornight) { case day: outans = true; cout << "It is day." << endl; break; case night: outans = true; cout << "It is night." << endl; break; } if(!outans) cout << "No facts are deducible." << endl; } cout << endl; }}
0 0
- uva 592 Island of Logic
- UVa 592 - Island of Logic
- UVa 592 - Island of Logic
- UVA 592 - Island of Logic
- UVA 592 Island of Logic
- UVa 592 - Island of Logic
- uva 592 Island of Logic (搜索)
- 592 - Island of Logic
- 592 - Island of Logic
- 592 - Island of Logic
- UVa 592 Island of Logic (有趣的枚举题)
- UvaOJ 592 Island of Logic
- Island of Logic uva 暴力枚举
- uva592 - Island of Logic
- [暴力搜索]Island of Logic UVA592
- POJ 1478 Island of Logic 笔记
- POJ 1478 / UVA592-Island of Logic -有点繁琐的暴力枚举+模拟
- [Leetcode]Number of Island
- K-based Numbers. Version 2
- poj 3278 Catch That Cow
- 脚本乐园 shell编程for in 循环
- 字符集和字符编码的理解
- 字符串-07. 说反话-加强版 (20)
- UVA 592 - Island of Logic
- 省创记录(一)
- 织梦channelartlist标签当前栏目高亮
- 反射实现加依赖注入
- jni练习(二)
- 一个很容易被坑的点(找出最大最小值并交换)
- 拿破仑经典名言
- 在input中右边加上一个图标的css样式
- 黑马程序员——java中集合的各种遍历方式总结