题目描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!
输入格式
输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);
M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,
每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。
往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。
输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。
输出格式
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是
罪犯,则输出 Cannot Determine;如果程序判断出没有人可能成为罪犯,则输出 Impossible。
AC代码又来了~:
#include<bits/stdc++.h>
#define debug cout
using namespace std;
const int maxn=30;
string name[maxn];
int ptr[maxn][maxn]; // 1 means is , -1 means not;
int day[maxn]; // means says day.
int day_can_be[maxn]; // can be that day ? 1 means is , -1 means is not.
int gul_can_be[maxn]; // persob i can be guilty or not , 1 means is , -1 means is not;
int may_be_ans[maxn]; // 0,1 means can be answer or not
string buf[1<<10];
map<string,int> person;
int n,m,p,mx,cnt,ans;
inline int getdate(string x)
{
if(x=="monday.") return 1;
if(x=="tuesday.") return 2;
if(x=="wednesday.") return 3;
if(x=="thursday.") return 4;
if(x=="friday.") return 5;
if(x=="saturday.") return 6;
if(x=="sunday.") return 7;
return puts("Wrong spelling ! Fuck you!"),-1;
}
inline char convchar(char x)
{
if( x>='A' && x<='Z' )
return x-'A'+'a';
else return x;
}
inline void convstring(string &x)
{
for(unsigned i=0;i<x.length();i++)
x[i] = convchar(x[i]);
}
inline char nextchar(int arg=0)
{
static char buf[1<<10],*st;
if(arg)
{
fgets(buf,1<<10,stdin),st=buf;
int i;
for(i=0;i<1<<10&&buf[i];i++)
if( buf[i]=='\r' )
buf[i] = '\n';
buf[i] = '\n';
}
return *st++;
}
inline void getline()
{
cnt = 0;
char c=nextchar(1);
cnt = 1;
while( c != '\n' )
{
if(c==' ')
{
if( person.find(buf[cnt]) == person.end() )
convstring(buf[cnt]);
cnt++;
}
else
buf[cnt] = buf[cnt] + c;
c = nextchar();
}
while( buf[cnt]=="" ) cnt--;
convstring(buf[cnt]);
}
inline void resbuf()
{
for(int i=1;i<=cnt;i++)
buf[i].clear(),
buf[i].resize(0);
}
inline void explain()
{
if( buf[2]!="i" && buf[2]!="today" && person.find(buf[2])==person.end() ) return;
const int id = person[buf[1]];
if( buf[2]=="today" )
{
int dd = getdate(buf[4]);
if( day[id] && day[id]!=dd )
{
ans = -2;
return;
}
day[id] = dd;
}
else if( buf[4]=="guilty." )
{
int tar = buf[2]=="i" ? id : person[buf[2]];
if( ptr[id][tar] && ptr[id][tar]!=1 )
{
ans = -2;
return;
}
ptr[id][tar] = 1;
}
else if( buf[5]=="guilty." )
{
int tar = buf[2]=="i" ? id : person[buf[2]];
if( ptr[id][tar] && ptr[id][tar]!=-1 )
{
ans = -2;
return;
}
ptr[id][tar] = -1;
}
}
inline void reslogic()
{
memset(day_can_be,0,sizeof(day_can_be));
memset(gul_can_be,0,sizeof(gul_can_be));
}
inline void logic(int x,int mul,int& flag)
{
if(day[x])
{
if( day_can_be[day[x]] && day_can_be[day[x]]!=mul )
{
flag=0;
return;
}
day_can_be[day[x]] = mul;
}
for(int i=1;i<=n;i++)
if(ptr[x][i])
{
const int pp = ptr[x][i]*mul;
if( gul_can_be[i] && gul_can_be[i]!=pp )
{
flag = 0;
return;
}
gul_can_be[i] = pp;
}
}
inline bool judgedate()
{
int ret=0;
for(int i=1;i<=7;i++)
if( ~day_can_be[i] )
ret += day_can_be[i];
return ret<2;
}
inline void judgegul()
{
int pos = -1,siz=n;
for(int i=1;i<=n;i++)
{
if( !~gul_can_be[i] ) --siz;
else if( gul_can_be[i] == 1 )
{
pos = i;
break;
}
}
if( siz>1 && !~pos ) // can not determine , maybe multi guilty .
{
ans = -1;
return;
}
if( siz==1 && !~pos )
for(int i=1;i<=n;i++)
if( !gul_can_be[i] )
{
may_be_ans[i] = 1;
return;
}
for(int i=1;i<=n;i++)
if( i!=pos && gul_can_be[i] == 1 ) // must be multi guilty in this statement
return;
may_be_ans[pos] = 1;
}
inline int count(int x)
{
int ret=0;
while(x)
ret++,
x -= (x&-x);
return ret;
}
inline int getans()
{
int ret = 0;
for(int i=1;i<=n;i++)
if( may_be_ans[i] )
ret++,
ans = i;
return ret;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
mx = (1<<n);
for(int i=1;i<=n;i++)
{
cin>>name[i];
person[name[i]] = person[name[i]+":"] = i;
}
char c = nextchar(1);
while(c!='\n') c=nextchar();
for(int i=1;i<=p;i++)
{
resbuf();
getline();
explain();
}
if( ans == -2 )
return puts("Impossible"),0;
for(int s=0;s<mx;s++)
{
if( count(s) != m ) continue;
reslogic();
int flag =1;
for(int i=1;i<=n&&flag;i++)
if( s & (1<<(i-1)) )
logic(i,-1,flag);
else logic(i,1,flag);
if( flag && judgedate() )
judgegul();
}
if( !~ans )
return puts("Cannot Determine"),0;
if( !getans() )
return puts("Impossible"),0;
if( getans() > 1 )
return puts("Cannot Determine"),0;
cout<<name[ans]<<endl;
return 0;
}
创作不易,点点赞呗~
bye~