题目大意
12个银子,一个重了或轻了,其它重量都一样。现将数目相等的两堆银子放到天平上称,究竟是哪些银子以及称量的具体结果都已知。问重或轻的银子是哪个,重了还是轻了。
思路
调查员是怎样系统分析问题的?思路便是缩小范围、运用排除法。
用整数压缩状态分别表示哪些银子可能轻了,哪些可能重了。天平平衡时,两侧的所有银子都不可能是假银子;不平衡时,轻银子只有可能在低的那一边的银子中,重银子同理。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cassert>
using namespace std;
int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int caseCnt;
cin >> caseCnt;
while (caseCnt--)
{
int light = (1 << 12) - 1, heavy = (1 << 12) - 1;
string a, b, condition;
for (int i = 0; i < 3; i++)
{
cin >> a >> b >> condition;
int left = 0, right = 0;
for (int i = 0; i < a.size(); i++)
left |= (1 << a[i] - 'A');
for (int i = 0; i < b.size(); i++)
right |= (1 << b[i] - 'A');
if (condition == "even")
{
light = light & (~left) & (~right);
heavy = heavy & (~left) & (~right);
}
else
{
if (condition == "up")
swap(left, right);
light &= left;
heavy &= right;
}
}
int lightAns = -1;
for(int i = 0; i < 12; i++)
if ((1 << i) & light)
{
if (light - (1 << i) == 0)
lightAns = i;
break;
}
int heavyAns = -1;
for(int i=0; i<12; i++)
if ((1 << i) & heavy)
{
if (heavy - (1 << i) == 0)
heavyAns = i;
break;
}
assert(lightAns == -1 && heavyAns >= 0 || heavyAns == -1 && lightAns >= 0);
if (lightAns >= 0)
printf("%c is the counterfeit coin and it is light.\n", lightAns + 'A');
else
printf("%c is the counterfeit coin and it is heavy.\n", heavyAns + 'A');
}
return 0;
}