前面说完美立方,生理周期中的枚举都是比较明显的枚举,有些枚举条件是隐藏的枚举条件,下面通过例题来说明寻找隐藏的枚举条件。

1、题目描述

  • 例题:POJ1013称硬币
    有12枚硬币。其中有11枚真币和1枚假币。假币和真币重量不同, 但不知道假币比真币轻还是重。现在用一架天平称了这些币三次,告诉你称的结果,请你找出假币并且确定假币是轻是重(数据保证一能找出来)。

  • 输入
    第一行是测试数据组数。
    每组数据有三行,每行表示一次称量的结果。银币标号为A-L。每次称量的结果用三个以空格隔开的字符串表示:天平左边放置的硬币,天平右边放置的硬币平衡状态。其中平衡状态用"up",“down”,或"even"表示, 分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。

  • 输出
    输出哪一个标号的银币是假币,并说明它比真币轻还是重。

  • 输入样例
    1
    ABCD EFGH even
    ABCI EFJK up
    ABIJ EFGH even

  • 输出样例
    K is the counterfeit coin and it is light.

2、解题思路

这个题目与智力题不同,不是让你设计称量方法,而是已经给出称量方法,有了称量结果,并且保证在结果中一定可以找出哪个是假币,这个假币是轻还是重。

对于解题思路,这里是在讲解枚举,大方向肯定是枚举嘛,一共有12个硬币,对每一个硬币进行枚举。对于每一枚硬币先假设它是假币且是轻的,拿这个假设带入三次称量的结果中,看是否符合称量结果。如果符合,问题即解决,确定这个硬币是假币且轻。如果不符合,就假设这个硬币是假币且是重的,看是否符合称量结果。把所有硬币都试一遍,一定能找到这个假币且判判断出假币是轻还是重。

#include<iostream>
using namespace std;

char Left[3][6];	//天平左边硬币
char Right[3][6];	//天平右边硬币
char result[3][4];	//称重结果
//light为true时,假设假币为轻,为false时,假设假币为重
bool IsFake(char c, bool light);
int main()
{
	int t;//数据的组数
	cin >> t;
	while (t--)
	{
		for (int i = 0; i < 3;i++)//每一组有三次称量
			cin >> Left[i] >> Right[i] >> result[i];
		for (char c = 'A'; c <= 'L'; c++)
		{
			if (IsFake(c, true))
			{
				cout << c << " is the counterfeit coin and it is light." << endl;
				break;
			}
			if (IsFake(c, false))
			{
				cout << c << " is the counterfeit coin and it is heavy." << endl;
				break;
			}
		}
	}
	return 0;
}

bool IsFake(char c, bool light)
{
	for (int i = 0; i < 3; i++)
	{
		char *pLeft, *pRight;//指向天平两边的字符串
		if (light == true)
		{
			pLeft = Left[i];
			pRight = Right[i];
		}
		else				//如果假设假币是重的,则把称量结果左右对换
		{
			pLeft = Right[i];
			pRight = Left[i];
		}
		switch (result[i][0])
		{
		case 'u':             //天平右边高
			if (strchr(pRight, c) == NULL)
				return false;
			break;//break作用是结束switch循环,不加会进入下一个case
		case 'e':             //天平两端等高
			if (strchr(pLeft, c) ||strchr(pRight, c))
				return false;
			break;
		case 'd':             //天平右边低
			if (strchr(pLeft, c) == NULL)
				return false;
			break;
		}
	}
	return true;
}

对strchr函数说明如下:

char *strchr(const char * _Str,char _Val)
功能:查找字符串_Str中首次出现字符_Val的位置
说明:返回首次出现_Val的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL。
返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL

3、总结

寻找隐藏的枚举条件