P1106侦探推理
描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!
格式
输入格式
输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。
输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。
输出格式
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 Cannot Determine;如果程序判断出没有人可能成为罪犯,则输出 Impossible。
样例1
限制
每个测试点1s
提示
有说一句话的末尾无空格的么?..
来源
NOIP2003第二题
解析:直接枚举凶手是谁,今天星期几,然后判断是否合法即可。根据合法的情况数,得到答案。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max_m 20
#define max_p 100
#define max_len 250
using namespace std;
int m,n;
char name[max_m+20][max_len+20];
struct tnode{int x,xq;
bool y[max_m+20];
}person[max_m+20];
char zy[5][30]={"I am guilty.","I am not guilty.","is guilty.","is not guilty.","Today is "};
char day[8][20]={"-_-||","Monday.","Tuesday.","Wednesday.","Thursday.","Friday.","Saturday.","Sunday."};
int lz[5]={12,16,10,14,9};
int ld[8]={0,7,8,10,9,7,9,7};
int ln[max_m+20];
bool used[max_m+20],f[max_m+20];
bool jia[max_m+20];
void readdata()
{
int i,j,k,p,len,l,r;
char s[max_len+20];
scanf("%d%d%d\n",&m,&n,&p);
for(i=1;i<=m;i++)gets(name[i]),ln[i]=strlen(name[i]);
for(i=1;i<=m;i++)person[i].x=person[i].xq=0;
for(i=1;i<=p;i++)
{
gets(s),len=strlen(s);
for(r=0;r<len && s[r]!=':';r++);
for(j=1;j<=m;j++)
if(strncmp(name[j],s,r)==0)break;
if(j>m || used[j])continue;
l=r+2,r=l;
//check 0
if(strncmp(zy[0],s+l,lz[0])==0)
{
if(person[j].y[j] && (person[j].x!=0 && person[j].x!=j))used[j]=1;
person[j].x=j;
f[j]=1;
continue;
}
//check 1
if(strncmp(zy[1],s+l,lz[1])==0)
{
if(person[j].x==j)used[j]=1;
person[j].y[j]=1;
f[j]=1;
continue;
}
//注意有人叫 Today 的情况
//check 4
if(strncmp(zy[4],s+l,lz[4])==0)
{
for(l+=lz[4],k=1;k<=7;k++)
if(strncmp(s+l,day[k],ld[k])==0)break;
if(k<=7)
{
if(person[j].xq!=0 && person[j].xq!=k)used[j]=1;
person[j].xq=k;
f[j]=1;
continue;
}
}
for(;r<len && s[r]!=' ';r++);
for(k=1;k<=m;k++)
if(ln[k]==r-l && strncmp(name[k],s+l,r-l)==0)break;
if(k>m)continue;
l=r+1;
//check 2
if(strncmp(s+l,zy[2],lz[2])==0)
{
if(person[j].y[k] || (person[j].x!=0 && person[j].x!=k))used[j]=1;
person[j].x=k;
f[j]=1;
continue;
}
//check 3
if(strncmp(s+l,zy[3],lz[3])==0)
{
if(person[j].x==k)used[j]=1;
person[j].y[k]=1;
f[j]=1;
}
}
}
int get(int xx,int yy)
{
memset(jia,0,sizeof(jia));
int i,j,k,sum=0;
for(i=1;i<=m;i++)if(!used[i] && f[i])
{
if(person[i].x!=0 && person[i].x!=xx)
{
jia[i]=1,sum++;
continue;
}
if(person[i].xq!=0 && person[i].xq!=yy)
{
jia[i]=1,sum++;
continue;
}
if(person[i].y[xx])
jia[i]=1,sum++;
}
for(i=1;i<=m;i++)if(jia[i])
{
if(person[i].x==xx || person[i].xq==yy)return 30;
for(j=1;j<=m;j++)if(j!=xx && person[i].y[j])return 30;
}
return sum;
}
void work()
{
int i,j,k,s1,s2,ans=0;
for(s1=0,i=1;i<=m;i++)if(!f[i])s1++;
for(i=1;i<=m;i++)if(!used[i])
for(j=1;j<=7;j++)
{
s2=get(i,j);
if(s2<=n && n<=s2+s1)
{
if(ans!=0)
{
printf("Cannot Determine\n");
return;
}
ans=i;
break;
}
}
if(ans==0)printf("Impossible\n");
else printf("%s\n",name[ans]);
}
int main()
{
readdata();
work();
return 0;
}