题目简介:
在《三体》中的三体文明接触了人类文明以后逐渐开始学会了说假话,于是三体社会中流行起了聚在一起评论别人说的话是真是假的活动。有一天,N个人(编号范围[0,N−1])聚在一起,每个人都说了一句:“a i说的是真/假话”。现在,围观的你想知道他们每个人说的是真还是假?
输入格式
第一行一个整数N,表示有N个人后面接着N行,其中第i行表示编号为i的人说的话,每行有两个整数a
i和bi,表示编号为i的人说编号为a i的人说的是真话(b i=1)或假话(b i=0)
数据范围:1<=N<=15,0<=ai<N,bi∈{0,1}
输出格式
N个整数,第i个整数为1表示编号为 i 的人实际在说真话,为0表示编号为 i 的人实际在说假话。
若有多种情况,则输出字典序最小的一个。
例如:
input | output |
---|---|
2 0 0 1 0 | 0 1 |
3 1 1 0 1 0 0 | 0 0 1 |
解释:
第一组数据:一共有2个人,第一个人说0号说的是假(0)话,第二个人说1号说的是假(0)话。
第二组数据:一共有3个人,第一个人说1号说的是真(1)话,第二个人说0号说的是真(1)话,第三个人说0号说的是假(0)话。这个时候有两种情况是对的,即1 1 0 和 0 0 1, 但输出字典序小的 0 0 1
思路:
1.首先假设可能的情况, 暴力从全是假话即全为0开始,遍历到全是真话即全为1。要求按照字典序输出,就可以想到是真值表的增加方式。
2.按照所假设的情况进行推理比较,如果某个人说的话与我所假设的矛盾那么就在真值表加一继续遍历,直到我的假设与他们所说的话没有矛盾。
3.输出最后的真值表即为答案
代码:
#include <iostream>
using namespace std;
int n;
int p[2][15]={0};//k said that what p[0][k] said is p[1][k]
int t[15]={0};//truth table, what k said is t[k]
int add_t(){
t[n-1]++;
int carry=0;
for(int i=n-1;i>=0;i--){
t[i]+=carry;
carry=t[i]/2;
t[i]%=2;
}
return carry;//when t[0]--t[n-1] are all 1, return 1;else return 0;
}
int inv(int a){
if(a) return 0;
else return 1;
}
int main(){
cin>>n;
int i;
for(i=0;i<n;i++){
cin>>p[0][i]>>p[1][i];
}
do{
int flag=1;//flag==1 represent that there's no logical conflict
for(int k=0;k<n;k++){
if(t[k]&&t[p[0][k]]!=p[1][k]||!t[k]&&t[p[0][k]]==p[1][k]){//there's a logical conflict
flag=0;break;
}
}
if(flag==1) break;
}while(inv(add_t()));
for(i=0;i<n;i++){
cout<<t[i]<<' ';
}
}
最后完结撒花!!!