注意换行符!!!
如果你使用getchar()系列函数读入,并且用换行符判定是否结束,则换行符会导致你WA掉!
linux下换行符为'\n',windows下换行符为'\r\n',如果数据是windows下造的,你就把'\r'也给当成字符串内容了,不wa才怪。
所以,你可以选择建立一个缓存区,把所有的'\r'替换成'\n',进行计算。
读取一整行的方法:
fgets(char* dst,size_t buf_size,File* file)
最后一个参数传stdin即可。不要用scanf("%[^\n]",str),因为你不知道最后的换行符是啥!
另外为了预防文末没换行的情况,手动在缓存区末补上一个'\n'。
具体算法不多说了,先预处理出每个人表示的意思,然后二进制状压枚举撒谎的人,如果这个状态的大小与所给人数相同,则进行计算。记得判定矛盾。可能这个状态是互相矛盾的,则不应更新答案。
如果输入存在矛盾,直接输出impossible。
如果一个状态有多个人未知,且没有人必定为罪犯则多解。
如果多个状态推出不同的罪犯,则多解。
如果一个状态只有一个人未知,其余的人都一定不是罪犯,则用这个不确定的人是罪犯去更新答案。
最后数一下有多少个人可能是罪犯,统计size,如果size为0则输出impossible,为1则输出人名,其余情况输出多解。
最后上代码:
css
#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;
}