题目翻译
莎莉·琼斯(Sally Jones)有十几美元的旅行者银元。 但是,只有十一枚硬币是真实的银元。 一枚硬币是伪造的,即使它的颜色和大小与真实的银元没有区别。 伪造的硬币的重量与其他硬币的重量不同,但是Sally不知道它比真实的硬币重还是轻。
幸好,莎莉有一位朋友向她借了一个非常准确的余额表。 朋友将允许Sally进行三次称重才能找到假币。 例如,如果Sally相互称重两个硬币并且秤保持平衡,则她知道这两个硬币是正确的。 现在,如果莎莉称重
真正的硬币中的一个相对于第三枚硬币,秤不平衡,然后Sally知道了第三枚硬币是伪造的,她可以根据放置在其上的余额是上升还是下降来分辨它是轻还是重。
通过仔细选择她的称重,Sally可以确保她将精确地找到三个称重的硬币。
输入
输入的第一行是整数n(n> 0),用于指定要遵循的个案数。 每种情况由三行输入组成,每行称重一次。 萨莉(Sally)用字母A–L标识了每个硬币。 称量信息将由两串字母,然后是上,下或偶数之一给出。 第一个字母字符串代表左侧余额上的硬币; 第二个字符串,右边余额的硬币。 (Sally总是在右侧余额上放置与左侧余额相同数量的硬币。)第三个位置中的单词将告诉您余额右侧是向上,向下还是保持不变。
思路分析
思路:逐一判断每个金币是否为真。
1,当天平为even 时,里面的金币都为真;
2,天平不是even时,假的金币在天平了,不在里面的都为真,同时将天平里的金币标记。分为轻和重。
3,当一个金币既是轻,又是重时,是真的。
第三点也很重要,比如下面这组数据,even的条件很弱,我们必须从两次up,down中辨别真假,对与AB他在上面的时候是重的一方,下面又轻了,说明他不是决定性的因素。
ABCDEF GHIJKL up
ABHLEF GDIJKC down
CD HA even
输出为假的金币。
附上一组数据:
12
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
AGHL BDEC even
JKI ADE up
J K even
ABCDEF GHIJKL up
ABC DEF even
I J down
ABCDEF GHIJKL up
ABHLEF GDIJKC down
CD HA even
A B up
B A down
A C even
A B up
B C even
DEFG HIJL even
ABC DEJ down
ACH IEF down
AHK IDJ down
ABCD EFGH even
AB IJ even
A L down
EFA BGH down
EFC GHD even
BA EF down
A B up
A C up
L K even
ACEGIK BDFHJL up
ACEGIL BDFHJK down
ACEGLK BDFHJI down
ACEGIK BDFHJL up
ACEGIL BDFHJK down
ACEGLK BDFHJI up
sample output
K is the counterfeit coin and it is light.
I is the counterfeit coin and it is heavy.
I is the counterfeit coin and it is light.
L is the counterfeit coin and it is light.
B is the counterfeit coin and it is light.
A is the counterfeit coin and it is heavy.
A is the counterfeit coin and it is light.
L is the counterfeit coin and it is heavy.
A is the counterfeit coin and it is light.
A is the counterfeit coin and it is heavy.
L is the counterfeit coin and it is light.
K is the counterfeit coin and it is heavy.
#include<iostream>
#include<map>
#include<string>
#include<string.h>
using namespace std;
int coins[12];//条件码 0:待确定 1:真的 2:未曾判断 所有硬币最后只能有一个待确定,就是假的
int cnt = 0, weight[12];//已经确认为真的数目,weight:如果是假的,是重:1还是轻:-1。
int main() {
int n; cin >> n;
string s1, s2, s3;
while (n--) {
for (int i = 0; i < 12; i++)coins[i] = 2;
memset(weight, 0, sizeof(weight));
for (int i = 0; i < 3; i++) {
cin >> s1 >> s2 >> s3;
if (s3[0] == 'e') {
for (int j = 0; j < s1.size(); j++)coins[s1[j] - 'A'] = 1;
for (int j = 0; j < s2.size(); j++)coins[s2[j] - 'A'] = 1;
}
else if (s3[0] == 'u') {//右边轻
for (int j = 0; j < s1.size(); j++)
{//不是真的就可能是假的
if (coins[s1[j] - 'A'] == 2)coins[s1[j] - 'A'] = 0, weight[s1[j] - 'A'] = 1;
else if (weight[s1[j] - 'A'] != 1) {//之前称过,而且不是重的一方
coins[s1[j] - 'A'] = 1;
}
}
for (int j = 0; j < s2.size(); j++) {
if (coins[s2[j] - 'A'] == 2)coins[s2[j] - 'A'] = 0, weight[s2[j] - 'A'] = -1;
else if (weight[s2[j] - 'A'] != -1) {
coins[s2[j] - 'A'] = 1;
}
}
for (int j = 0; j < 12; j++) {
int a = s1.find(j + 'A'), b = s2.find(j + 'A');
if (a == -1 && b == -1)
coins[j] = 1;//不在假的里面就是真的
}
}
else {//左边轻
for (int j = 0; j < s1.size(); j++)
{//不是真的就可能是假的
if (coins[s1[j] - 'A'] == 2)coins[s1[j] - 'A'] = 0, weight[s1[j] - 'A'] = -1;
else if (weight[s1[j] - 'A'] != -1) {
coins[s1[j] - 'A'] = 1;
}
}
for (int j = 0; j < s2.size(); j++) {
if (coins[s2[j] - 'A'] == 2)coins[s2[j] - 'A'] = 0, weight[s2[j] - 'A'] = 1;
else if (weight[s2[j] - 'A'] != 1) coins[s2[j] - 'A'] = 1;
}
for (int j = 0; j < 12; j++) {
int a = s1.find(j + 'A'), b = s2.find(j + 'A');
if (a == -1 && b == -1)
coins[j] = 1;//不在假的里面就是真的
}
}
}
for (int i = 0; i < 12; i++) {
if (coins[i] == 0) {
char s = i + 'A';
if (weight[i] == 1) s1.assign("heavy");
else s1.assign("light");
cout << s << " is the counterfeit coin and it is " << s1 << "." << endl; break;
}
}
}
}