您的位置:首页 > 其它

网友聚会解答

2008-03-19 23:25 155 查看
网友聚会
某论坛想组织一次小规模的网友聚会,邀请论坛的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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: