问题描述
某场比赛过后,你想要知道A~E五个人的排名是什么,于是要求他们每个人说了一句话。(经典的开头……-_-!)得了第1名的人23,说了假话;得了第5名的人不好意思,也说了假话;为了使求解问题简单,第3名同样说了假话。(奇数名次说假话)
输入格式 共5行,各行依次表示A~E说的话。
每行包含一个形如“A>=3”的名次判断,即一个大写字母+关系运算符+一个数字,不包含空格。
大写字母A~E,关系运算<、<=、=、>=、>、!=,数字1~5。注意:等于是“=”不是“==”! 输出格式
可能有多解,请按照字典序输出排名序列,每个解一行 最后一行输出解的数量样例输入
A=2
D=5
E>3
A>2
B!=1
样例输出
ACDEB
AECBD
BADCE
BCADE
BDACE
CEADB
CEBDA
7
刷题看到这题好像挺好玩的,百度到的答案觉得没自己写得好,所以这里就写一下咯
题目分析一下,就是全排列组合”ABCDE”,然后将组合对应的表达式解析并判断.
比如说题目给的例子:输出结果第1个”ACDEB”组合.
组合索引 | 索引所对应的值 | 所对应表达式索引 | 所对应表达式 |
---|---|---|---|
0 | ‘A’ | 0 | “A = 2” |
1 | ‘C’ | 2 | “E > 3” |
2 | ‘D’ | 3 | “A > 2” |
3 | ‘E’ | 4 | “B != 1” |
4 | ‘B’ | 1 | “D = 5” |
按题目要求,组合索引为0,2,4的表达式结果取反,最后全部表达式用与关系运算为真时就是正确答案之一.
上代码
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
//输入的5个表达式(expression)字符串
string expStr[5];
//解析字符串,permutation为当前组合字符串,expression为表达式
bool parseExpression(string permutation, string expression);
//判断'=',"!=" numberIndex为表达式后面的数字所对应索引
bool m_equal(string permutation, string expression, int numberIndex);
//判断'<',">="
bool m_less(string permutation, string expression, int numberIndex);
//判断'>',"<="
bool m_greater(string permutation, string expression, int numberIndex);
int main()
{
for (size_t i = 0; i < 5; i++)
cin >> expStr[i];
string perStr = "ABCDE";
int count = 0;
do
{
//perStr当前组合字符串,表达式的索引为组合的值,就是上面的表格
if (!parseExpression(perStr, expStr[perStr[0] - 'A']) && parseExpression(perStr, expStr[perStr[1] - 'A'])
&& !parseExpression(perStr, expStr[perStr[2] - 'A']) && parseExpression(perStr, expStr[perStr[3] - 'A'])
&& !parseExpression(perStr, expStr[perStr[4] - 'A']))
{
cout << perStr << endl;
++count;
}
} while (next_permutation(perStr.begin(), perStr.end()));
cout << count << endl;
system("pause");
return 0;
}
解析表达式,并返回表达式所对应的值.
表达式按题目所说,不考虑出错,只有两种长度,3和4,一个字母,一个数字,关系运算符一个或两个字符,一个字符时,数字在索引2,两个字符时,数字在索引3.
bool parseExpression(string permutation, string expression)
{
if (expression.size() == 3)
{
switch (expression[1])
{
case '=':
return m_equal(permutation, expression,2);
case '<':
return m_less(permutation, expression,2);
case '>':
return m_greater(permutation, expression,2);
}
}
else
{
//不等于就是等于取非,小于等于就是大于,大于等于就是小于
switch (expression[1])
{
case '!':
return !m_equal(permutation, expression,3);
case '<':
return !m_greater(permutation, expression,3);
case '>':
return !m_less(permutation, expression,3);
}
}
}
判断等于,直接判断表达式的第一个字母是不是和表达式数字为组合索引所对应的值一样.举例:组合”ACDEB”,表达式”A=2”,判断 表达式[0](‘A’) == 组合[‘2’ - ‘0’ - 1](‘C’),返回false.
(索引减一是因为输入表达式数字范围是1~5)
bool m_equal(string permutation, string expression, int numberIndex)
{
if (expression[0] == permutation[expression[numberIndex] - '0' - 1])
return true;
else
return false;
}
判断小于,遍历组合,找到相同字符,判断索引值,等价大于等于取非
bool m_less(string permutation, string expression, int numberIndex)
{
for (size_t i = 0; i < permutation.size(); i++)
if (expression[0] == permutation[i])
if (i < (expression[numberIndex] - '0' - 1))
return true;
else
return false;
}
判断大于,等价小于等于取非
bool m_greater(string permutation, string expression, int numberIndex)
{
for (size_t i = 0; i < permutation.size(); i++)
if (expression[0] == permutation[i])
if (i > (expression[numberIndex] - '0' - 1))
return true;
else
return false;
}
运行结果: