1、这道题真是折腾了我好几天,感觉需要很强的逻辑学功底才能做出来,目前我还写不出来。。。
2、摘抄了一位网友的题解,变量的名字都是很纯正的英文,感觉像是外国人写的,即使这样,也受益良多。
3、define的运用使程序的可读性一下子提高,枚举的时候也相当巧妙,还有亦或的运用,lying函数的运用。。。
4、首先先判断是否“不可能”,“不可能”的条件是“没有一种枚举情况可能”;再判断能否推断出关于居民的结论;再判断能否推断出关于时间的结论;最后如果能推断出至少一点结论,说明“并不是不能确定结论”,否则打印“不能确定任何结论”,注意和“不可能”区分开来,前者是多种情况符合,后者是没有情况符合。
#include<cstdio>
#define DIVINE 0
#define EVIL 1
#define HUMAN 2
#define DAY 0
#define NIGHT 1
#define MAXPERSONS 5
#define STATENUM 486
using namespace std;
int state[STATENUM];
int type(int state,int p){
state/=2;
while(p--) state/=3;
return(state%3);
}
int lying(int state,int p){
int daynight,t;
daynight=state%2;
t=type(state,p);
return(t==EVIL||(t==HUMAN&&daynight==NIGHT));
}
void init(){
for(int i=0;i<STATENUM;i++) state[i]=1;
}
void scanline(){
int i,neg,speaker,target,t,truee;
char s[50];
gets(s);
speaker=s[0]-'A';
if(s[3]=='I'&&s[4]=='t'){
for(int i=0;i<STATENUM;i++){
truee=((i%2==DAY&&s[9]=='d')||(i%2==NIGHT&&s[9]=='n'));
if(lying(i,speaker)==truee) state[i]=0;
}
return;
}
if(s[5]=='a') target=speaker;
else target=s[3]-'A';
neg=(s[8]=='n');
switch(s[8+4*neg]){
case 'd':t=DIVINE;break;
case 'e':t=EVIL;break;
case 'h':t=HUMAN;break;
case 'l':
for(int i=0;i<STATENUM;i++){
truee=neg^lying(i,target);
if(lying(i,speaker)==truee) state[i]=0;
}
return;
}
for(int i=0;i<STATENUM;i++){
truee=neg^(type(i,target)==t);
if(lying(i,speaker)==truee) state[i]=0;
}
return;
}
void output(){
int deduction,i,j,possible[MAXPERSONS],daynight;
static int caseno=1;
char names[3][10]={"divine","evil","human"};
printf("Conversation #%d\n",caseno++);
for(int i=0;i<MAXPERSONS;i++)
possible[i]=-1;
daynight=-1;
for(int i=0;i<STATENUM;i++)
if(state[i]){
if(daynight!=-1&&daynight!=i%2)
daynight=-2;
else if(daynight==-1)
daynight=i%2;
for(j=0;j<MAXPERSONS;j++){
if(possible[j]!=-1&&possible[j]!=type(i,j))
possible[j]=-2;
else if(possible[j]==-1)
possible[j]=type(i,j);
}
}
if(daynight==-1)
{
printf("This is impossible.\n\n");
return;
}
deduction=0;
for(int i=0;i<MAXPERSONS;i++){
if(possible[i]>=0){
printf("%c is %s.\n",i+'A',names[possible[i]]);
deduction=1;
}
}
if(daynight>=0){
printf("It is %s.\n",daynight==DAY?"day":"night");
deduction=1;
}
if(!deduction)
printf("No facts are deducible.\n");
printf("\n");
}
int main()
{
int i,n;
while(scanf("%d\n",&n)==1&&n){
init();
for(int i=0;i<n;i++) scanline();
output();
}
return 0;
}