NOIP 2003 侦探原理 大模拟+枚举

来源:互联网 发布:ssh2权限管理系统源码 编辑:程序博客网 时间:2024/04/30 07:42

题目大意:有一些小孩闲着没事玩游戏,他们M个人中有N个人肯定说假话,剩下的人肯定说实话,有一个人是罪犯,求这个罪犯。

他们会说出如下的话:

证词内容 
证词含义
I am guity
我是罪犯
I am not guity.
我不是罪犯
Xxx is guity
Xxx是罪犯(Xxx表示某个同学的名字)
XXX is not guity
Xxx不是罪犯
Today is XXX
今天是XxxXxx表示星期几


思路很简单,就是枚举今天是那一天和罪犯是谁就行。但这个题有很多巨坑。

巨坑1:上面的表格是错的。。(我直接从oj粘下来的,注意他的“guity”的拼写是错的,一定要复制“guilty”)

巨坑2:测试数据里有个人叫“ I ” 的人。。(还好没有叫Today的人。。)

巨坑3:如果你把一个句子判断完了,要看看后面还有没有字符。如果有的话,该句作废。。。


废话不多说,上CODE:


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 300using 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");elseprintf("%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;elseinfo[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;elseinfo[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;elsestatus[info[i].from] = 0;}else {if(status[info[i].from] == 0)return false;elsestatus[info[i].from] = 1;}}else if(info[i].effect == 2) {if(!Lie(info[i],guilty)) {if(status[info[i].from] == 1)return false;elsestatus[info[i].from] = 0;}else {if(status[info[i].from] == 0)return false;elsestatus[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;elsereturn true;}else {if(information.person == guilty)return false;elsereturn true;}}


0 0