解题思路
QAQ
大大大大大大大大暴力
对于证词的内容判断,采用say[i].substr(a,n)截取,表示从a开始截取n个字符。
用 z f , n z f , d a t zf,nzf,dat zf,nzf,dat可以分别储存每个人的证词中的信息,分别为他指明的罪犯是谁,罪犯不是谁,今天的日期。
然后枚举罪犯分别是谁,check每种情况下每个人的证词是否有出入,这里可以用azf[25],adat[10],表示那些人被指认为罪犯,那些人不是罪犯,以及那些日期不是今天。
Tips:
- 日期只有一个是真的,不能同时成立
- 只有一个人不确定,其他人都不是罪犯,那个人就是罪犯
- 考虑完所有情况后,有几个人都可能是罪犯(在某些情况中,他们可以被准确推断为唯一罪犯)属于Cannot Determine
- 考虑完所有情况后,都没有一种能准确推断唯一罪犯,即有些情况不矛盾但不唯一确认,就是Cannot Determine
代码
#include<bits/stdc++.h>
using namespace std;
map<string,int>mp,date;
bool flag,flag1;
int m,n,P;
string name[25],p[110],say[110],ps[110],s,ss,ans;
int zf[110],dat[110],nzf[110],v[25];
int azf[25],adat[10],da;
char c;
bool check(){
bool ok=1;
da=0;
memset(azf,0,sizeof(azf));
memset(adat,0,sizeof(adat));
for(int i=1;i<=P;i++)
{
if(v[mp[ps[i]]]==1)
{
if(zf[i]!=0)
{
if(azf[zf[i]]==0)
azf[zf[i]]=2;//1为罪犯,2为非罪犯
else if(azf[zf[i]]==1)
{
ok=0;
break;
}
}
if(nzf[i]!=0)
{
if(azf[nzf[i]]==0)
{
azf[nzf[i]]=1;
}
else if(azf[nzf[i]]==2)
{
ok=0;
break;
}
}
if(dat[i]!=0)
{
if(adat[dat[i]]==0)
adat[dat[i]]=2;
else if(adat[dat[i]]==1)
{
ok=0;
break;
}
}
}
else
{
if(zf[i]!=0)
{
if(azf[zf[i]]==0)
azf[zf[i]]=1;
else if(azf[zf[i]]==2)
{
ok=0;
break;
}
}
if(nzf[i]!=0)
{
if(azf[nzf[i]]==0)
azf[nzf[i]]=2;
else if(azf[nzf[i]]==1)
{
ok=0;
break;
}
}
if(dat[i]!=0)
{
if(adat[dat[i]]==2)
{
ok=0;
break;
}
if(da==0)
adat[dat[i]]=1,da=dat[i];
else if(da!=dat[i])
{
ok=0;
break;
}
}
}
}
if(ok==1)return 1;
else return 0;
}
void work(int dep,int last)
{
if(dep>n)
{
if(check()==1)
{
flag1=1;//此情况不矛盾
string anss;
int cnt=0,okk=0,t=0;
for(int i=1;i<=m;i++)
{
if(azf[i]==1)
{
if(okk)
return;
anss=name[i];
okk=1;
}
if(azf[i]==2)
cnt++;
if(azf[i]!=2)t=i;
}
if(cnt==m-1){
okk=1;
anss=name[t];
}
if(flag)
{
if(ans!=anss)//tips3
{
printf("Cannot Determine\n");
flag=-1;
return;
}
}
else if(okk){
flag=1;
ans=anss;
}
}
return;
}
if(last>m)return;
if(flag==-1)return;
if(n-dep+1>m-last+1)
return;
for(int i=last;i<=m;i++)
{
v[i]=1;
work(dep+1,i+1);
if(flag==-1)return;
v[i]=0;
}
}
int main(){
freopen("logic.in","r",stdin);
freopen("logic.out","w",stdout);
date["Monday."]=1;date["Tuesday."]=2;date["Wednesday."]=3;date["Thursday."]=4; date["Friday."]=5; date["Saturday."]=6;date["Sunday."]=7;
scanf("%d%d%d",&m,&n,&P);
for(int i=1;i<=m;i++)
{
cin>>name[i];
mp[name[i]]=i;
}
for(int i=1;i<=P;i++)
{
cin>>p[i];
s=p[i].substr(0,p[i].size()-1);
ps[i]=s;
getline(cin,say[i]);
int len=say[i].size();
if(say[i]==" I am guilty.")
{
zf[i]=mp[s];
continue;
}
if(say[i]==" I am not guilty.")
{
nzf[i]=mp[s];
continue;
}
ss=say[i].substr(0,10);
if(ss==" Today is ")
{
//cout<<i<<endl;
ss=say[i].substr(10,len-3);
dat[i]=date[ss];
// cout<<dat[i]<<endl;
continue;
}
for(int j=0;j<len;j++)
{
if(say[i][j]=='i')
{
ss=say[i].substr(j);
if(ss=="is not guilty.")
{
ss=say[i].substr(1,j-2);
nzf[i]=mp[ss];
}
if(ss=="is guilty.")
{
ss=say[i].substr(1,j-2);
zf[i]=mp[ss];
}
}
}
}
work(1,1);
if(flag==1)
cout<<ans;
else if(flag1==1)
printf("Cannot Determine\n");
else printf("Impossible\n");
}