题目大意
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. ", lightAns + 'A'); else printf("%c is the counterfeit coin and it is heavy. ", heavyAns + 'A'); } return 0; }