POJ1013 Counterfeit Dollar

题目大意

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;
}

  

posted @ 2018-06-03 00:32  headboy2002  阅读(180)  评论(0编辑  收藏  举报