题目名称 2361. 逻辑岛
输入输出 logicisland.in/out
难度等级 ★★★★
时间限制 1000 ms (1 s)
内存限制 256 MiB
测试数据 15
题目来源 Gravatarmouse 于2016-06-20加入
开放分组 全部用户
提交状态
分类标签
分享题解
通过:3, 提交:31, 通过率:9.68%
Gravatar月落九天 100 0.003 s 0.29 MiB C++
Gravatarミント 100 0.004 s 0.31 MiB C++
Gravatarfmj 100 0.004 s 0.31 MiB C++
GravatarSaionji 80 0.021 s 0.27 MiB C++
GravatarSaionji 80 0.033 s 0.25 MiB C++
GravatarSaionji 20 0.004 s 0.31 MiB C++
Gravatarmouse 20 0.004 s 0.31 MiB C++
GravatarSaionji 20 0.005 s 0.29 MiB C++
Gravatarha sa ki 20 0.012 s 0.29 MiB C++
Gravatarha sa ki 20 0.031 s 0.31 MiB C++
本题关联比赛
16暑期热身练习
关于 逻辑岛 的近10条评论(全部评论)
膜拜神犇,这道题有什么卵用吗?
GravatarNVIDIA
2016-07-31 16:32 4楼
回复 @fmj : 666666
Gravatar..
2016-07-03 10:49 3楼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50 + 10;
class kanato{//Kanato-chan——.//
public:
int sp, re, st;//speaker, reference, status.
bool fa;//false(is not ...).
}sen[maxn];//sentence.
bool night = false;
int sta[maxn], is[maxn], n;
inline int f(bool flag){//false==1貌似会不被判断为真...orz Update: 废话. 懒得重打就这么凑合着看吧.
if(flag)return 1;
return 0;
}
inline bool check(){
bool flag = false;//这句话是否成立.
for(int i=1;i<=n;i++){//逐个检验每句话关于时间与身份的信息.
if(sen[i].re==-1){//关于时间.
if(sen[i].st==f(night))flag = true;
else flag = false;
}
else if(sen[i].st<3){//关于身份.
if(sen[i].st==sta[sen[i].re])flag = true;
else flag = false;
}
else if((sta[sen[i].re]==1)||(sta[sen[i].re]==2)&&night)flag = true;//魔鬼或者是晚上的人.
else flag = false;
//对于说这句话的家伙.
if(sen[i].fa)flag = !flag;//"Is not ...".
if((sta[sen[i].sp])==1||(sta[sen[i].sp]==2&&night))flag = !flag;
if(flag==false)//如果这句话不成立.
return false; //那就无解咯.
}
return true;//找到了一个可行解.
}
inline bool impos(bool a){
for(int i=1;i<=5;i++)if(!is[i])return true;
if(!a)return true;
return false;
}
#define is_cha(x) ((x <= 'z' and x >= 'a') or (x <= 'Z' and x >= 'A'))
#define is_sym(x) ( x == '.' or x == ':' or x == ' ')
#define is_ch(x) (is_sym(x) or is_cha(x))
string get_line() {
char tmp = getchar();
string ans;
ans.clear();
while(!is_ch(tmp)) tmp = getchar();
while( is_ch(tmp)) {
ans = ans + tmp;
tmp = getchar();
}
return ans;
}
int main(){
freopen("logicisland.in", "r", stdin);
freopen("logicisland.out", "w", stdout);
int kase = 0;
//while(cin>>n){getchar();if(n==0)break;kase++;cout<<"Conversation #"<<kase<<endl;
memset(is, 0, sizeof(is));
memset(sta, 0, sizeof(sta));
memset(sen, 0, sizeof(sen));
night = false;
cin>>n;//getchar();//Read char '/n'.
for(int i=1;i<=n;i++){
string str;
str = get_line();
int name = str[0] - 'A' + 1, ref = -1;//Speaker, Mentioned.
str = str.substr(3, str.length());
if(str[0]=='I'&&str[2]=='a'){//I am.
ref = name;
str = str.substr(5, str.length());//go over.
}
else if(str[2]=='i'&&str[3]=='s'){//X is.
ref = str[0] - 'A' + 1;
str = str.substr(5, str.length());//go over.
}
else {//It is night/day.
ref = -1;//算了用中文注释吧, 没有人被提到的情况ref设为-1.
str = str.substr(6, str.length());//继续往后面找相关信息.
}
sen[i].sp = name;sen[i].re = ref;
if(str[0]=='n'&&str[1]=='o'){sen[i].fa = true;str = str.substr(4, str.length());}//Is not.
else sen[i].fa = false;
//
string tmp = "121213413";tmp = tmp.substr(1, tmp.length());
if(str.compare("divine.")==0)sen[i].st = 0;
else if(str.compare("evil.")==0)sen[i].st = 1;
else if(str.compare("human.")==0)sen[i].st = 2;
else if(str.compare("lying.")==0)sen[i].st = 3;
else if(str.compare("day.")==0)sen[i].st = 0;
else if(str.compare("night.")==0)sen[i].st = 1;
else cout<<"Orz Cstdio"<<endl;//哎嘿.
}
//枚举, 搞大新闻.
int tnight = 0, kount = 0;
for(night=false;kount<=1;night=!night, kount++)
for(sta[1]=0;sta[1]<=2;sta[1]++)
for(sta[2]=0;sta[2]<=2;sta[2]++)
for(sta[3]=0;sta[3]<=2;sta[3]++)
for(sta[4]=0;sta[4]<=2;sta[4]++)
for(sta[5]=0;sta[5]<=2;sta[5]++)
if(check()){
for(int j=1;j<=5;j++)is[j] |= (1<<sta[j]);//拆二进制存储状态. 1, 2, 4.
tnight = tnight | (1<<f(night));
}
if(impos(tnight)){cout<<"This is impossible."<<endl<<endl;return 0;}//continue;}
bool flag = false;//有没有找到的推论.
for(int j=1;j<=5;j++){//先输出身份信息.
string out;//cout<<is[j]<<endl;
if(is[j]==(1<<0))out = "divine.";
else if(is[j]==(1<<1))out = "evil.";
else if(is[j]==(1<<2))out = "human.";
else continue;
flag = true;
printf("%c is ", (char)(j+'A'-1));cout<<out<<endl;
}
if(tnight==(1<<0)){flag = true;cout<<"It is day."<<endl;}
if(tnight==(1<<1)){flag = true;cout<<"It is night."<<endl;}
if(flag==false)cout<<"No facts are deducible."<<endl;
cout<<endl;
return 0;
}
Gravatarfmj
2016-07-02 16:56 2楼
Gravatarfmj
2016-07-02 16:56 1楼

2361. 逻辑岛

★★★★   输入文件:logicisland.in   输出文件:logicisland.out   简单对比
时间限制:1 s   内存限制:256 MiB

【题目描述】


逻辑岛上有三种居民:神、魔鬼和人,神总是说真话,魔鬼总是撒谎,而人则是白天说真话,晚上撒谎。每一个居民都能认出其它居民的身份。

一个社会学家要去逻辑岛上考察,由于他无法根据居民的长相来确定其身份,他需要你为他提供一个通信分析仪通过居民们的谈话来推理出一些事实。其中他最感兴趣的事实是现在是白天还是夜晚,以及说话的居民的身份。


【输入格式】


输入文件第一行为一个整数n,表示谈话中语句的个数。

接下来有n行,每行为某个居民所说的一个语句,每个语句行的第一个符号为讲话者的姓名,姓名均为单个的大写字母A,B,C,D,E,姓名之后有一个冒号“:”和一个空格,语句接下来的格式如下:

I am [not] ( divine | human | evil | lying ).

X is [not] ( divine | human | evil | lying ).

It is ( day | night ).

方括号[]表示其中的单词也许会出现,也许不会出现,圆括号()表示其中由|隔开的单词只会出现一种。X为A,B,C,D,E中的一个,任一语句行都不会出现两个连续的空格,谈话中包含的语句最多不超过50个。


【输出格式】


如果依照规则这组谈话是不可能发生的,则输出“This is impossible.”(不包括双引号,以下同);

如果无法推理出所需要的事实,输出“No facts are deducible.”;

此外则要求输出所有能够推理出的事实,输出格式如下:

X is ( divine | human | evil ).

It is ( day | night ).

X由一个大写字母即讲话者的姓名代替,居民的身份信息必须首先输出(按姓名的字母顺序),接下来输出白天或夜晚的信息(如果无法推理出来是白天还是晚上则不需输出)。


【样例输入】

输入样例1:
1
A: I am evil.

输入样例2:
3
A: B is human.
B: A is evil.
A: B is evil.

【样例输出】

输出样例1:
A is human.
It is night.

输出样例2:
A is evil.
B is divine.

【提示】

在此键入。

【来源】

在此键入。