1013 Counterfeit Dollar:我们不要暴力:优美的确定假币(内含一大组数据+各种情况分析)

题目翻译

莎莉·琼斯(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;
			}
		}
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值