CERC2016 gym101173L

2 篇文章 0 订阅

Problem L: Lost Logic

Gustav is reading about 2-satisfiability, a well known problem of assigning truth values to boolean variables in order to satisfy a list of constraints — simple logical formulas involving two variables each. We are using n variables x1,x2,…,xn that can take on values 0 (false) and 1 (true). A constraint is a formula of the form a → b where both a and b are possibly negated variables. As usual,→denotes logical implication: a→b is 0 only when a is 1 and b is 0. The negation of variable a is denoted by !a. Given an assignment of values to variables, we say that the constraint is satisfied if it evaluates to 1. Gustav has constructed alist of constraints and correctlyconcluded that there areexactlythreedifferent assignments of values to variables that satisfy all the constraints. Gustav has wrote down all three assignments but has, unfortunately, lost the list of constraints. Given three assignmentsof n values tovariables, find any listconsisting ofat most500 constrainssuch that the three given assignments are the only assignments that satisfy all the constraints.
Input
The first line contains an integer n (2≤n≤50) — the number of variables. Three lines follow, each describing one assignment. The k-th line contains n space-separated integers vk 1,vk 2,…,vk n, where each vk i is either 0 or 1 and denotes the value of the variable xi in the k-th assignment. All three assignments will be different.
Output
If there is no solution output a single line containing the integer−1. Otherwise, the first line should contain an integer m where 1≤m≤500 — the number of constraints in your solution. The k-th of the following m lines should contain the k-th constraint. Each constraint should be a string constructed according to the following rules:
• A variable is a string of the form “xi” where i is an integer between 1 and n inclusive written without leading zeros.
• A literal is a string consisting of a variable possibly preceded by the “!” character.
• A constraint is a string of the form “a -> b” where both a and b are literals. The implication sign consists of the “minus” character and the “greater-than” character and there is a single space character both before and after the implication sign.

Example
input
3
0 0 0
0 1 0
1 0 0
output
3
x1 -> !x2
x3 -> x1
x3 -> x2
input
4
0 0 1 0
1 0 0 0
1 0 1 1
output
-1

题意

n个变量,给出三种赋值,让你写出约束条件,仅满足这三种赋值。

解法

1. 处理常数

例如第一组测试用例的x3 ,恒等于0. 那么有

x3->!x3

若变量恒等于1,那么:

!x->x

2. 划分等价类

有很多变量是等价的 x1 == x2:

x1 -> x2 x2 -> s1

x1 == !x2

x1 -> !x2 x2 -> !x1

3. 计算

因为只有三种约束,容易知道等价类最多有4种,即0,1,2,3
抛去0(因为0已经被约束)
剩下的1,2,3中,最多只能有两种,若出现三种,那么无解。(手推)
剩下两种的情况时,直接枚举可能出现的蕴含表达式即可。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int SIZE = 1;

int a[505];
vector<int> v[4];

struct node {
    int f1, f2, n1, n2;
    node(int _f1, int _n1, int _f2, int _n2) {
        f1 = _f1;
        n1 = _n1;
        f2 = _f2;
        n2 = _n2;
    }
};

vector<node> res;

int main() {
    int n;
    scanf("%d",&n);
    for(int j = 0; j < 3; j++) {
        for(int i = 1; i <= n; i++) {
            int t;
            scanf("%d",&t);
            a[i] |= t << j;
        }
    }
    for(int i = 1; i <= n; i++) {
        if(a[i] == 0) {
            res.push_back(node(0,i,1,i));
        }
        else if(a[i] == 7) {
            res.push_back(node(1,i,0,i));
        }
        else if(a[i] <= 3 && a[i] >= 0) {
            v[a[i]].push_back(i);
        }
        else {
            int t = a[i] ^ 7;
            v[t].push_back(i);
        }
    }
    if(v[1].size() > 0 && v[2].size() > 0 && v[3].size() > 0) {
        printf("-1");
        return 0;
    }
    for(int vi = 1; vi <= 3; vi++) {
        for(int i = 1; i < v[vi].size(); i++) {
            if(a[v[vi][0]] == a[v[vi][i]]) {
                res.push_back(node(0,v[vi][0],0,v[vi][i]));
                res.push_back(node(1,v[vi][0],1,v[vi][i]));
            }
            else {
                res.push_back(node(0,v[vi][0],1,v[vi][i]));
                res.push_back(node(1,v[vi][0],0,v[vi][i]));
            }
        }
    }
    for(int i = 1; i <= 3; i++) {
        if(!v[i].size()) continue;
        for(int j = i + 1; j <= 3; j++) {
            if(!v[j].size()) continue;
            int a1 = a[v[i][0]], a2 = a[v[j][0]];
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(0,v[i][0],0,v[j][0]));
            a1 = a[v[i][0]]^7;
            a2 = a[v[j][0]];
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(1,v[i][0],0,v[j][0]));
            a1 = a[v[i][0]];
            a2 = a[v[j][0]]^7;
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(0,v[i][0],1,v[j][0]));
            a1 = a[v[i][0]]^7;
            a2 = a[v[j][0]]^7;
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(1,v[i][0],1,v[j][0]));
            a1 = a[v[j][0]];
            a2 = a[v[i][0]];
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(0,v[j][0],0,v[i][0]));
            a1 = a[v[j][0]]^7;
            a2 = a[v[i][0]];
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(1,v[j][0],0,v[i][0]));
            a1 = a[v[j][0]];
            a2 = a[v[i][0]]^7;
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(0,v[j][0],1,v[i][0]));
            a1 = a[v[j][0]]^7;
            a2 = a[v[i][0]]^7;
            if((a1&1) == 0 || ((a1&1) == 1 && (a2&1)==1 ))
                if((a1&2) == 0 || ((a1&2) == 2 && (a2&2)==2 ))
                    if((a1&4) == 0 || ((a1&4) == 4 && (a2&4)==4 ))
                        res.push_back(node(1,v[j][0],1,v[i][0]));
        }

    }
    printf("%d\n",res.size());
    for(node nd: res) {
        printf("%sx%d -> %sx%d\n",nd.f1?"!":"",nd.n1,nd.f2?"!":"",nd.n2);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值