网友聚会解答

 
网友聚会
某论坛想组织一次小规模的网友聚会,邀请论坛的n(1<=n<=4)个版主和论坛上m(1<=m<=10)个积极的网友参加。这m个网友是根据在论坛上的发文贡献从大到小排列后选出来的。组织者在论坛上公布了聚会计划,也按贡献大小公布了这m个网友的名单,然后逐个向这m个网友询问参加意向。有趣的是,这些网友都没有直接说参加还是不参加,而是声明了各自参加聚会的条件,而且这些条件只和版主以及贡献比自己大的那些网友是否参加有关。
组织者统计了一下,各种条件其实可以归纳为4类,每一类都和另外一个或两个人是否参加有关。如果用X和Y来表示某个版主或者某个网友,那么这4类条件是:
1) 我不参加,除非X和Y都参加。
2) 我参加,除非X和Y都不参加。
3) 如果X参加,那么我不参加,否则我参加。
4) 我参加,除非X去并且Y不去。
组织者发现,对于以上各类条件,只要确定了条件中X和Y是否参加,那么该网友是不是参加也就确定了。因此在上述4类条件下,该网友是否参加可分别用逻辑表达式X v Y、X ^ Y、~X和X > Y来表示,其中4个符号分别表示析取、合取、否定和推演。
组织者还发现,虽然各个论坛版主是否会参加聚会还不确定,但是根据各个网友声明的参加条件进行推理,其实有些网友一定不会参加聚会,而有些网友一定会参加聚会,当然还有一些网友是否参加最终要看各个版主的参加情况。
组织者请你写一个程序,由他输入各个网友声明的条件,请你输出各个网友的参加情况。输入格式是这样的:用P0、P1、…、Pn-1分别表示各个版主,用A0、A1、…、Am-1分别表示各个网友,且下标越小表示该网友贡献越大。程序的输入有多行,第一行是以空格分开的两个整数n和m,之后的m行依次描述各个网友声明的条件,并严格依照以下格式:
Ai空格Tj空格?空格Sk
其中Ai依次为A0、A1、…、Am-1;?可以为“~”、“>”、“^”或“v”之一;若?为“~”,则Tj为“X0”(表示只与后面Sk的参加情况有关),若?为“>”、“^”或“v”,则Tj为Aj(0<=j<i)或Pj(0<=j<n);Sk为Ak(0<=k<i)或Pk(0<=k<n)。
程序的输出要求是以空格分开的m个整数(最后一个整数之后没有空格直接换行),分别表示A0、A1、…、Am-1的参加情况。不管各位版主的参加情况如何,如果该网友一定会参加聚会则用1表示,如果该网友一定不会参加聚会则用-1表示,如果必须根据版主的参加情况才能确定则用0表示。
【输入样例1】
1 2
A0 X0 ~ P0
A1 A0 v P0
【输出样例1】
0 1
【输入样例2】
3 4
A0 P0 > P1
A1 P1 > P2
A2 P2 > P3
A3 P0 > P3
【输出样例2】
0 0 0 0
【输入样例3】
2 3
A0 P0 > P1
A1 P1 > A0
A2 X0 ~ A1
【输出样例3】
0 1 -1

 #include <iostream>
using namespace std;

struct Condition
{
 char type; // 逻辑运算符
 char left; // 左项,X或P或A
 int i;  // 左项下标
 char right; // 右项,P或A
 int j;  // 右项下标
 bool value; // 真假的取值
};
Condition A[10]; // 记录表达式情况
int TrueTimes[10] = {0}; // 记录取真次数
bool P[4];  // 变元

void SetP(int i) // 枚举版主参加情况
{
 P[0] = bool(i & 0x1);
 P[1] = bool(i & 0x2);
 P[2] = bool(i & 0x4);
 P[3] = bool(i & 0x8);
}

bool LeftValue(const Condition &a) // 左项取值
{
 if (a.left == 'A')
  return A[a.i].value;
 else
  return P[a.i];
}

bool RightValue(const Condition &a) // 右项取值
{
 if (a.right == 'A')
  return A[a.j].value;
 else
  return P[a.j];
}

int OutValue(int allTimes, int trueTimes)
{
 if (trueTimes == 0)
  return -1;
 if (trueTimes == allTimes)
  return 1;
 return 0;
}

int main()
{
 int n, m;  // 读入n, m
 cin >> n >> m;

 char c;   // 辅助用
 for (int i = 0; i < m; i++)  // 读入m个逻辑表达式
  cin >> c >> c >> A[i].left >> A[i].i
  >> A[i].type >> A[i].right >> A[i].j;

 int allTimes = 1 << n; // 先计算总的枚举次数

 for (int i = 0; i < allTimes; i++)
 {  
  SetP(i); // 枚举版主参加情况

  // 依次计算网友参加情况
  for (int j = 0; j < m; j++)
  {
   switch (A[j].type)
   {
    case '~':
     A[j].value = !RightValue(A[j]);
     break;
    case '>':
     A[j].value = !LeftValue(A[j]) || RightValue(A[j]);
     break;
    case '^':
     A[j].value = LeftValue(A[j]) && RightValue(A[j]);
     break;
    case 'v':
     A[j].value = LeftValue(A[j]) || RightValue(A[j]);
     break;
   }
   if (A[j].value)  // 参加聚会
    TrueTimes[j] ++;
  }
 }

 cout << OutValue(allTimes, TrueTimes[0]);
 for (int i = 1; i < m; i++)
  cout << ' ' << OutValue(allTimes, TrueTimes[i]);
 cout << endl;
 
 return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
大家好!欢迎来到这次难得的初中聚会!我是今天的主持人,C知道。很高兴能够见到这么多熟悉的面孔,大家都变得更加成熟和自信了。 首先,让我们回忆一下初中的时光。那是我们成长的重要阶段,充满了欢声笑语、友谊和回忆。在这里,我们可以追溯到我们的最初梦想,回顾我们的成长历程。 现在,请允许我介绍一下今天的活动安排。我们将有一系列有趣的互动游戏和表演节目,让我们度过一个愉快而难忘的夜晚。 首先,我们将进行一个回忆挑战游戏。每个班级将派出一名代表,通过回答问题来测试你们对初中时期的记忆力。这将是一个考验你们团队合作和智力的时刻。 接下来,我们将有一些特别的表演节目。如果你有才艺,无论是歌唱、舞蹈、表演还是其他形式,请尽情展示出来。这是一个展示你们才华的机会,让我们一起享受每个人的精彩表演。 当然,聚会还有一个重要的环节,那就是互相交流。请大家穿越时光隧道,回到初中时期的那个年代。和你的同学们聊聊近况,分享你们的工作、生活和梦想。这将是一个亲密无间的时刻,让我们彼此更加了解和支持。 最后,我想感谢所有筹备这次聚会的工作人员,他们用心准备了这场聚会,让我们有机会再次相聚。同时,也要感谢每一位同学的到来,你们的参与是这次聚会成功的关键。 在这个特殊的夜晚,让我们一起分享欢笑、回忆过去,并为未来祝福彼此。希望这次聚会能够成为我们友谊长久的见证,让我们记住初中时光的美好。 祝愿大家度过一个难忘的夜晚!谢谢大家!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值