题意解析

mm位同学中有一位凶手,小明要根据他们的pp句证词找出凶手。 已知有nn位同学一直说谎

思路解析

首先第一思路肯定是根据nn的值来枚举所有可能性 因此,要先处理相矛盾的证词。 对于每句证词,有以下六种可能: 1.自报 2.举报别人 3.自证 4.证明他人 5.聊星期 6.废话 很明显1,2为同类,3,4为同类,废话不用管 所以我们只要想办法把不同证词区分开就行了

思路一

用证词的关键词来分类 但可举反例,无法区分废话

思路二

将证词和人分开处理,更简单直接 可以用map将对字符串的处理转为对数的处理,进一步简化代码

将证词分成xxyy是凶手,xxyy不是凶手,xx说今天是星期几。

接下来是对可能性的分析

每句证词都可分为真话和假话,关于凶手和天气 共四类 直接用基本的循环就行了

接着枚举可能的星期和凶手,判断是否可行(说谎人数为nn,只说真话或假话)。

最后按题意输出

代码

1.输入

long long m,n,p,sd[25][7],ck[25][25],nk[25][25],cnt1[105],cnt2[105],f[105];
string name[25],s,x;
map<string,int> mp,mp2,ns;
void run(int idx,string say){
	if(say==" I am guilty.") ck[idx][idx]=1;//我是凶手
	else if(say==" I am not guilty.") nk[idx][idx]=1;//我不是凶手
	else if(say==" Today is Monday.")sd[idx][0]++;//星期
	else if(say==" Today is Tuesday.")sd[idx][1]++;
	else if(say==" Today is Wednesday.")sd[idx][2]++;
	else if(say==" Today is Thursday.")sd[idx][3]++;
	else if(say==" Today is Friday.")sd[idx][4]++;
	else if(say==" Today is Saturday.")sd[idx][5]++;
	else if(say==" Today is Sunday.")sd[idx][6]++;
	else if(mp[say])ck[idx][mp[say]]=1;//xxx是凶手
	else if(mp2[say])nk[idx][mp2[say]]=1;//xxx不是凶手
}

2.判断

int res1=0,res2=0,res3=0;//真话,假话,嫌疑人数
	memset(cnt1,0,sizeof cnt1);
	memset(cnt2,0,sizeof cnt2);
//星期不符
	for(int i=1;i<=m;i++){
		if(sd[i][x]!=0)cnt2[i]=1;
		for(int j=0;j<=6;j++){
			if(sd[i][j]!=0 and j!=x){
				cnt1[i]=1;
				break;
			}
		}
	}
//凶手不符
	for(int i=1;i<=m;i++){
		if(ck[i][y]==1)cnt2[i]=1;
		if(nk[i][y]==1)cnt1[i]=1;
		for(int j=1;j<=m;j++){
			if(ck[i][j]==1 and j!=y){
				cnt1[i]=1;
			}
			if(nk[i][j]==1 and j!=y){
				cnt2[i]=1;
			}
		}
	}
	for(int i=1;i<=m;i++){
		res1+=cnt1[i];
		res2+=cnt2[i];
		if(cnt1[i]==1 and cnt2[i]==1)return 0;
		if(cnt1[i]==0 and cnt2[i]==0)res3++;
	}
	if(n<=res1+res3 and res1<=n)return 1;
	else return 0;

0 条评论

目前还没有评论...