Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
暴力枚举+模拟,有点繁琐,内附代码+报告直接暴力,代码写得有点挫。。。 我的报告:http://blog.csdn.net/viphong/article/details/50198029 下面是代码+详细注释 #include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; struct node { char spker; char who; int is_not; string what; int d_or_n; }; node tm[55]; string ss; vector<int> sb[55]; set<char> ::iterator it; int main() { int n,i; int cnt=1; set<char> sb; while(scanf("%d",&n)!=EOF&&n) { sb.clear(); getchar(); for (i=1;i<=n;i++) { getline(cin,ss); string sub=ss.substr(3,ss.length()-3); //截取除去主语后的一句话 tm[i].d_or_n=-1; // 为-1表示本句话与时间无关 if (sub=="It is day.") { tm[i].spker=ss[0]; //记下说话人 tm[i].d_or_n=1;continue; //记下是白天还是黑夜 } if (sub=="It is night.") { tm[i].spker=ss[0]; tm[i].d_or_n=0;continue; } if (ss[3]=='I') //‘I’就是说话人自己 ss[3]=ss[0]; tm[i].spker=ss[0]; tm[i].who=ss[3]; sb.insert(tm[i].spker); //计算种类 sb.insert(tm[i].who); if (ss.find("not")!=string::npos) //如果找不到not,则为肯定句,找到则表示为否定句 tm[i].is_not=0; else tm[i].is_not=1; if (ss.find("divine")!=string::npos) //被认为是什么 tm[i].what="divine"; else if (ss.find("human")!=string::npos) tm[i].what="human"; else if (ss.find("evil")!=string::npos) tm[i].what="evil"; else if (ss.find("lying")!=string::npos) tm[i].what="lying"; } printf("Conversation #%d\n",cnt++); string what[6]; //what[i]存第i个人 当前的身份 int k; int flag=0; // impossible的情况(当且仅当说I am lying.才是此情况) int kind=sb.size(); //出现的种类数(最后要输出的种类数) int possible_way=0; //合法的身份方案, 如果仅有一种,则输出,否则表示都多种情况 int all=(int)pow(3.0,5); //枚举范围0-all string ans[6]; //用来保存 找到合法的身份方案后 的那5个身份 int has_change[6]; //用来记录 找到的多个合法方案中 某人的身份是否一样 (如果一样,表示某个人的身份在什么时候都是确定的,反之则否) memset(has_change,0,sizeof(has_change)); int ans_d_n=-1; //用来保存 找到合法的身份方案后 的时间,如果一直不变,表示这个时间也是固定的,同has_change数组的理 int has_changed_d_n=0; //记录 合法方案的时间是否改变,理由同上 int line=1; //标志 当前方案是否第一次出现, int day_night; //时间变量,1为白天,0为黑夜 int twice=0; //枚举 每种方案 在白天 和 黑夜下的情况 for (k=0;k<all;k++) { if (twice==1)//第二次 把时间看作黑夜,并且k--回到上个方案 { twice++; k--; day_night=0; continue; } if (twice==0)//第一次 把时间看作白天 { twice++; day_night=1; } if (twice==2) //复位 twice=0; int tmp=k; for (i=1;i<=5;i++) //枚举身份 { if (tmp%3==0) what[i]="divine"; else if (tmp%3==1) what[i]="human"; else what[i]="evil"; tmp=tmp/3; } int find_ans=1; //是否找到一个合法方案 for (i=1;i<=n;i++) { if (tm[i].d_or_n!=-1) //如果第i句话与时间相关 { if (day_night==tm[i].d_or_n) //如果第i句话时间与当前方案时间相同,即本句话为真 { if (what[tm[i].spker-'A'+1]=="divine") //神族说真话,没问题 continue; if (what[tm[i].spker-'A'+1]=="evil") //恶魔说真话,本方案不合法,结束 {find_ans=0;break;} if (what[tm[i].spker-'A'+1]=="human") //人 { if (day_night==1) continue; //白天说真话,ok else {find_ans=0;break;} //晚上说真话,本方案不合法,结束 } } else //如果第i句话时间与当前方案时间相同,即本句话为假 ,下面的具体就不分析了 { if (what[tm[i].spker-'A'+1]=="divine") {find_ans=0;break;} if (what[tm[i].spker-'A'+1]=="evil") continue; if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) {find_ans=0;break;} else continue; } } } //下面的都是本句话与时间 无关的情况 if (tm[i].what=="lying") //谁谁谁 lying 的情况 { if (tm[i].is_not==1) //如果说 某人【在】说谎 { if (tm[i].spker==tm[i].who) //如果自己说自己说谎, 这是唯一的 不可能的方案,flag标记,结束所有方案,输出答案 {flag=1; find_ans=1;break;} int isreal; //其余情况要先判断 这句话是否为真 (先不考虑说话人,只考虑说的话) if (what[tm[i].who-'A'+1]=="divine") //神不可能撒谎,本句话为假 isreal=0; if (what[tm[i].who-'A'+1]=="human") //人类撒谎根据时间 { if (day_night==1) isreal=0; else isreal=1; } if (what[tm[i].who-'A'+1]=="evil") //恶魔撒谎 isreal=1; if (isreal) //如果 shuo 的是真话 { if (what[tm[i].spker-'A'+1]=="divine") //神说真话,合法 continue; if (what[tm[i].spker-'A'+1]=="human") //人是否合法得看时间 { if (day_night==0) { find_ans=0;break; } } if (what[tm[i].spker-'A'+1]=="evil") //恶魔不说真话 { find_ans=0;break; } } else //说的是假话 { if (what[tm[i].spker-'A'+1]=="divine") {find_ans=0;break;} //矛盾 if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) {find_ans=0;break;} //本应该说真话却说假话 else if (day_night==0) continue; //晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") continue; } } else // //如果说 某人【不在】说谎 { int isreal; //依旧先判断 话的真假 if (what[tm[i].who-'A'+1]=="divine") isreal=1; if (what[tm[i].who-'A'+1]=="human") { if (day_night==1) isreal=1; else isreal=0; } if (what[tm[i].who-'A'+1]=="evil") isreal=0; if (isreal) //如果 shuo 的是真话 { if (what[tm[i].spker-'A'+1]=="divine") continue; if (what[tm[i].spker-'A'+1]=="human") { if (day_night==0) { find_ans=0;break; } } if (what[tm[i].spker-'A'+1]=="evil") { find_ans=0;break; } } else //如果说的是假话 { if (what[tm[i].spker-'A'+1]=="divine") {find_ans=0;break;} //矛盾 if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) {find_ans=0;break;} //本应该说真话却说假话 else if (day_night==0) continue; //晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") continue; } } } else //下面的情况 就是 xxx是什么身份 这种句式 { if (tm[i].is_not==1) //如果是肯定句 { if (tm[i].what==what[tm[i].who-'A'+1])//与被描述者身份一致,本句为真话 { if (what[tm[i].spker-'A'+1]=="divine") continue; if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) continue; //本应该说真话却说假话 else if (day_night==0) {find_ans=0;break;} //晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") {find_ans=0;break;} } else //与被描述者身份不一致,本句为假话 { if (what[tm[i].spker-'A'+1]=="divine") {find_ans=0;break;} //矛盾 if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) {find_ans=0;break;} //本应该说真话却说假话 else if (day_night==0) continue; //晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") continue; } } else //如果整句话是否定句 { if (tm[i].what==what[tm[i].who-'A'+1]) //与被描述者身份一致,本句为假话 { if (what[tm[i].spker-'A'+1]=="divine") {find_ans=0;break;} //矛盾 if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) {find_ans=0;break;} //本应该说真话却说假话 else if (day_night==0) continue; //晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") continue; } else //与被描述者身份不一致,本句为真话 { if (what[tm[i].spker-'A'+1]=="divine") continue; if (what[tm[i].spker-'A'+1]=="human") { if (day_night==1) continue; //本应该说真话却说假话 else if (day_night==0) {find_ans=0;break;}//晚上说假话 } if (what[tm[i].spker-'A'+1]=="evil") {find_ans=0;break;} } } } } if (flag) //impossible的情况 break; if (find_ans) //找到一种合法方案 { int h; for (h=1;h<=5;h++) //储存答案 { if (line) //如果是第一次找到合法方案,直接存下来,并在后面去掉首次标记 { ans[h]=what[h];continue; } if (ans[h]!=what[h]) //非第一次找到答案,先比较当前答案与以前的是否一致 { ans[h]=what[h]; //更新答案并且 has_change[h]=1; //如果不一致,标志这个人的身份是不确定的 } } if (ans_d_n!=day_night&&!line) //更新时间,并看是否一直不变 has_changed_d_n=1; ans_d_n=day_night; //储存时间 possible_way++; //方案数++ line=0; } } if (possible_way==0||flag) //无合法方案,或者遇到flag情况 printf("This is impossible.\n"); else if (possible_way>1) //方案有很多 { int has=0; //记录是否有输出过答案 it=sb.begin(); //遍历出现过的人 for (int h=1;h<=kind;h++,it++) { int p= (*it)-'A'+1; //出现过的人的编号 if (has_change[p]==0) //如果在多个方案中 身份都一样,则标明身份确定,输出,并更新标记 { printf("%c is %s.\n",p-1+'A',ans[p].c_str()); has=1; //表示输出过答案 } } if (has_changed_d_n==0) //如果时间在多个方案中不曾改变 if (ans_d_n!=-1) printf("It is %s.\n",(ans_d_n==1)?"day":"night"),has=1; //输出答案并更新标记 if (!has) //如果 人的身份或时间都不是确定的,输出 无法确定事实 printf("No facts are deducible.\n"); } else //如果方案只有一种。。。。必然就是合法的唯一的方案 { it=sb.begin(); for (i=1;i<=kind;i++,it++) { int p= (*it)-'A'+1; printf("%c is %s.\n",p-1+'A',ans[p].c_str()); } if (ans_d_n!=-1) printf("It is %s.\n",(ans_d_n==1)?"day":"night"); } printf("\n"); } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator