UVa 592 - Island of Logic

/*
    思路:枚举所有情况。
    this is impossible. 所以情况都不满足条件。
    No facts are deducible. 有满足条件的情况,但是情况之间没有交集,也就是说原条件不能推导出任何结论来。
    fact: 满足条件的情况之间的交集。
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

char kind[][20] = {"divine", "human", "evil"};
const int MAX_P = 5+5; //最大人数
int person[MAX_P]; //记录ABCD是人是妖
char name[MAX_P];  //记录对应的名字(考虑到只出现人名A、C,而不出现B等情况)
int name_order[MAX_P]; //记录A、B、C、D、E分别出现的顺序
int lying[MAX_P];  //0:lying 1:not lying
int time; //0:day, 1:night
int cur_p; //人数
struct line //台词
{
    int who_said; //who said
    int kind;// 0:句型1或2; 1:句型3
    int time; //0:day, 1:night
    int person; //person: 0-4
    int has_not; //not: 0, 1
    int id; //0-3, 3:lying
};
const int MAX_L = 50+5;
line lines[MAX_L];
int cur_l;
//结论
int found;
int result[MAX_P];
int r_time;
void dicide()
{
    for(int i=0; i<cur_p; i++) {
        switch(person[i]) {
            case 0: lying[i] = 0; break;
            case 2: lying[i] = 1; break;
            case 1: lying[i] = time;
        }
    }
    int ok = 1;
    for(int i=0; i<cur_l; i++) {
        int flag = 1; //0:结论取反, 1:结论不需要取反
        if(lying[lines[i].who_said]) flag = !flag; //如果说话人说谎,要取反
        if(lines[i].kind==0) { //句型1、2
            if(lines[i].has_not) flag = !flag;  //如果原来语句含有not, 要取反
            if(lines[i].id != 3) {
                if(flag && person[lines[i].person]!=lines[i].id) {
                    ok = 0; break;
                }
                if(!flag && person[lines[i].person]==lines[i].id) {
                    ok = 0; break;
                }
            } else { // X is lying.
                if(flag && !lying[lines[i].person]) {
                    ok = 0; break;
                }
                if(!flag && lying[lines[i].person]) {
                    ok = 0; break;
                }
            }
        } else { //句型3
            if(flag && time != lines[i].time) {
                ok = 0; break;
            }
            if(!flag && time == lines[i].time) {
                ok = 0; break;
            }
        }
    }
    if(ok) {
        if(!found) {
            memcpy(result, person, sizeof(person));
            r_time = time;
            found = 1;
        } else {
            for(int i=0; i<cur_p; i++) {
                if(person[i] != result[i]) {
                    result[i] = -1;
                }
            }
            if(r_time != time) r_time = -1;
        }
    }
}

void dfs(int cur)
{
    if(cur == cur_p) {
        time = 0;
        dicide();
        time = 1;
        dicide();
        return;
    }
    for(int i=0; i<3; i++) {
        person[cur] = i;
        dfs(cur+1);
    }
}

int insert_p(char n)
{
    for(int i=0; i<cur_p; i++) if(name[i] == n) {
        return i;
    }
    name[cur_p] = n;
    name_order[n-'A'] = cur_p;
    return cur_p++;

}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    int T = 0;
    while(scanf("%d", &cur_l) == 1) {
        if(!cur_l) break;
        char buff[10];
        cur_p = 0;
        memset(name_order, -1, sizeof(name_order));
        for(int i=0; i<cur_l; i++) {
            scanf("%s", buff);
            lines[i].who_said = insert_p(buff[0]);
            scanf("%s", buff);
            if(buff[1] == 't') { //句型3
                lines[i].kind = 1;
                scanf("%s", buff); // is
                scanf("%s", buff); // day | night;
                if(buff[0] == 'd') lines[i].time = 0;
                else lines[i].time = 1;
            } else { //句型1、2
                lines[i].kind = 0;
                if(buff[0] == 'I') {
                    lines[i].person = lines[i].who_said;
                } else {
                    lines[i].person = insert_p(buff[0]);
                }
                scanf("%s", buff);
                scanf("%s", buff);
                if(buff[0] == 'n') { // not
                    lines[i].has_not = 1;
                    scanf("%s", buff);
                }else {
                    lines[i].has_not = 0;
                }
                switch(buff[0]) {
                    case 'd': lines[i].id = 0; break; //divine
                    case 'h': lines[i].id = 1; break; //human
                    case 'e': lines[i].id = 2; break; //evil
                    case 'l': lines[i].id = 3; break; //lying
                }
            }
        }
        printf("Conversation #%d\n", ++T);
        found = false;
        dfs(0);
        int ok = 0;
        if(found) {
            for(int i=0; i<MAX_P; i++) {
                int order = name_order[i];
                if(order != -1 && result[order] != -1){
                    ok = 1;
                    printf("%c is %s.\n", i+'A', kind[result[order]]);
                }
            }
            if(r_time != -1) {
                ok = 1;
                printf("It is %s.\n", r_time?"night":"day");
            }
            if(!ok) printf("No facts are deducible.\n");
        } else {
            printf("This is impossible.\n");
        }
        printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值