题目大意:有一些小孩闲着没事玩游戏,他们M个人中有N个人肯定说假话,剩下的人肯定说实话,有一个人是罪犯,求这个罪犯。
他们会说出如下的话:
证词内容
|
证词含义
|
I am guity
|
我是罪犯
|
I am not guity.
|
我不是罪犯
|
Xxx is guity
|
Xxx是罪犯(Xxx表示某个同学的名字)
|
XXX is not guity
|
Xxx不是罪犯
|
Today is XXX
|
今天是Xxx(Xxx表示星期几
|
思路很简单,就是枚举今天是那一天和罪犯是谁就行。但这个题有很多巨坑。
巨坑1:上面的表格是错的。。(我直接从oj粘下来的,注意他的“guity”的拼写是错的,一定要复制“guilty”)
巨坑2:测试数据里有个人叫“ I ” 的人。。(还好没有叫Today的人。。)
巨坑3:如果你把一个句子判断完了,要看看后面还有没有字符。如果有的话,该句作废。。。
废话不多说,上CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 300 using namespace std; const char weekdays[10][20] = {"","Monday.","Tuesday.","Wednesday.","Thursday.","Friday.","Saturday.","Sunday."}; struct Complex{ int effect; int weekday; int from,person; bool opt; Complex() { weekday = 0; effect = 0; } }info[MAX]; int points,lies,sens; char src[MAX][50]; char temp[MAX]; inline void Work(char *s,int pos); inline void GetString(char *&s,char *aim); inline bool Check(int guilty,int week); inline bool Lie(Complex information,int guilty); int main() { cin >> points >> lies >> sens; for(int i = 1;i <= points; ++i) scanf("%s",src[i]); getchar(); for(int i = 1;i <= sens; ++i) { fgets(temp,1000,stdin); Work(temp,i); } bool found = false; int ans = -1; for(int i = 1;i <= points; ++i) { bool temp = false; for(int j = 1;j <= 7; ++j) { if(Check(i,j)) temp = true; } if(temp && !found) ans = i,found = true; else if(temp) { printf("Cannot Determine"); return 0; } } if(ans == -1) printf("Impossible"); else printf("%s",src[ans]); return 0; } inline void Work(char *s,int pos) { char temp[MAX]; GetString(s,temp); temp[strlen(temp) - 1] = '\0'; for(int i = 1;i <= points; ++i) if(!strcmp(temp,src[i])) info[pos].from = i; GetString(s,temp); if(!strcmp(temp,"Today")) { info[pos].effect = 1; GetString(s,temp); GetString(s,temp); for(int i = 1;i <= 7; ++i) if(!strcmp(temp,weekdays[i])) info[pos].weekday = i; if(*s != '\0' && *s != '\n') info[pos].effect = 0; } else if(!strcmp(temp,"I")) { info[pos].effect = 2; info[pos].person = info[pos].from; GetString(s,temp); if(!strcmp(temp,"is")) { int p = 0; for(int i = 1;i <= points; ++i) if(!strcmp("I",src[i])) p = i; info[pos].person = p; } GetString(s,temp); if(!strcmp(temp,"not")) info[pos].opt = false,GetString(s,temp); else if(!strcmp(temp,"guilty.")) info[pos].opt = true; else info[pos].effect = 0; if(*s != '\0' && *s != '\n') info[pos].effect = 0; } else { int p = 0; for(int i = 1;i <= points; ++i) if(!strcmp(temp,src[i])) p = i; if(p) { info[pos].effect = 2; info[pos].person = p; GetString(s,temp); GetString(s,temp); if(!strcmp(temp,"not")) info[pos].opt = false,GetString(s,temp); else if(!strcmp(temp,"guilty.")) info[pos].opt = true; else info[pos].effect = 0; if(*s != '\0' && *s != '\n') info[pos].effect = 0; } } } inline void GetString(char *&s,char *aim) { sscanf(s,"%s",aim); s += strlen(aim) + 1; } inline bool Check(int guilty,int week) { static int status[MAX]; memset(status,-1,sizeof(status)); for(int i = 1;i <= sens; ++i) { if(info[i].effect == 1) { if(info[i].weekday != week) { if(status[info[i].from] == 1) return false; else status[info[i].from] = 0; } else { if(status[info[i].from] == 0) return false; else status[info[i].from] = 1; } } else if(info[i].effect == 2) { if(!Lie(info[i],guilty)) { if(status[info[i].from] == 1) return false; else status[info[i].from] = 0; } else { if(status[info[i].from] == 0) return false; else status[info[i].from] = 1; } } } int cnt = 0; for(int i = 1;i <= points; ++i) if(!status[i]) cnt++; if(cnt > lies) return false; for(int i = 1;i <= points; ++i) if(status[i] == -1) cnt++; if(cnt < lies) return false; return true; } inline bool Lie(Complex information,int guilty) { if(information.opt) { if(information.person != guilty) return false; else return true; } else { if(information.person == guilty) return false; else return true; } }