经典智力题:经理年龄问题

一个经理有三个女儿,三个女儿的年龄加起来等于13,三个女儿的年龄乘起来等于经理自己的年龄,有一个下属已知道经理的年龄,但仍不能确定经理三个女儿的年龄,这时经理说只有一个女儿的头发是黑的,然后这个下属就知道了经理三个女儿的年龄。请问三个女儿的年龄分别是多少?为什么?


解答:


看似简单的题目做起来却让我费了不少脑子,真叫它“只有一个女儿的头发是黑的”这个条件给忽悠住了……呵呵~~~知道了正确答案后(真是羡慕网上达人们的智慧啊)才发现,哎~,这句话既是解决问题的关键,也是糊弄我们的陷阱。。。先来看看正确的解题思路吧。

首先,设三个女儿的年龄分别为x,y,z,经理的年龄为A,且x≥y≥z。(此处先不考虑“只有一个女儿的头发是黑的”这一条件,为什么一会解释)

则根据已知得:

     x+y+z=13 ………………………………①

    (三个女儿的年龄加起来等于13)
     xyz=A<60 ………………………………②

    (三个女儿的年龄乘起来等于经理的年龄,经理在职年龄应小于60岁)
     xyz-x>22 ………………………………③

    (经理有第一个女儿时应超过法定年龄)

解式2,z^3<xyz<60

则   z≤3

根据式1列表:

z y x A xyz-x
1 1 11 11 0
1 2 10 20 10
1 3 9 27 18
1 4 8 32 24
1 5 7 35 28
1 6 6 36 30
2 2 9 36 27
2 3 8 48 40
2 4 7 56 49
2 5 6 60 54
3 3 7 63 56
3 4 6 72 66
3 5 5 75 70


表中满足式2、3条件的解如下:
 

z y x A xyz-x
1 4 8 32 24
1 5 7 35 28
1 6 6 36 30
2 2 9 36 27
2 3 8 48 40
2 4 7 56 49
2 5 6 60 54

此时追加条件1:“有一个下属已知道经理的年龄,但仍不能确定经理三个女儿的年龄”

假设此时我们知道了经理的年龄,比如是35,那么他女儿的年龄肯定就确定了,为(1,5,7)。但是题设说下属知道了经理的年龄还不知道其女儿的年龄,这说明满足条件的解一定有两个以上,而表中只有36这一组数据具有两个不同的解(1,6,6)(2,2,9),所以范围确定至此。

再追加条件2:“只有一个女儿的头发是黑的”


也就是说,x>y≥z,所以答案就很清楚了,为(2,2,9)。

反过来看,此题目实际上分为两个部分——已知条件部分和追加判断部分。“只有一个女儿的头发是黑的”是追加的判断条件,没有作对的问题就出在把追加的判断条件作为了已知条件来处理了。

像我一样,大部分的人在开始时总会把“只有一个女儿的头发是黑的”作为已知,得出x>y≥z的结论,并用其进行求解。这个结论是没错,但是逻辑顺序却错了,我们来看:

设三个女儿的年龄分别为x,y,z,经理的年龄为A,但x>y≥z(此处考虑了“只有一个女儿的头发是黑的”这一条件)

同理,根据式2得z≤3

根据式1列表为:
 

z y x A xyz-x
1 1 11 11 0
1 2 10 20 10
1 3 9 27 18
1 4 8 32 24
1 5 7 35 28
2 2 9 36 27
2 3 8 48 40
2 4 7 56 49
2 5 6 60 54
3 3 7 63 56
3 4 6 72 66

则上表中满足式2、3条件的解如下:
 

z y x A xyz-x
1 4 8 32 24
1 5 7 35 28
2 2 9 36 27
2 3 8 48 40
2 4 7 56 49
2 5 6 60 54

比较前面发现:(1,6,6)这组数据没了。。。这上哪解去啊,这个时候有人就想了,孩子多少岁长头发来?1岁?2岁?3岁?呵呵,实际上已经差之毫厘,谬以千里了。。。

 

附上代码:

//已知条件是:假设三个女儿的年龄分别为x,y,z,经理年龄为A,则x+y+z=13,x*y*z=A<60,z<=3,x>=y>=z;追加条件是x>y>=z(只有一个女儿的头发是黑的)

#include <iostream>
#include <vector>
#include <map>
using namespace std;

struct DaughterAge  //三个女儿的年龄的组合
{
	int x;
	int y;
	int z;
};


int main()
{
	vector<DaughterAge>vecDaughterAge; //三个女儿年龄的可能值组合的集合
	
	map<int,int>mManagerAgeAndCounts; //根据vecDaughterAge得到对应的该经理的年龄和次数的集合
	
	vector<DaughterAge>::iterator  vIter;
	map<int,int>::iterator mIter;
	
	int x,y,z;  //三个女儿的年龄
	int a;      //经理的年龄
	DaughterAge tmp; //临时变量,临时存储数据
	
	
	//枚举所有可能的情况
	for(z=1; z<=3; ++z)  
	{
		for(y=1; y<13-z; ++y)
		{
			x=13-z-y;  //根据y和z值求出x
			a=x*y*z;   //求出对应的a
			if((a <60) && (a-x >22) && (x>=y && y>=z)) //判断这组数据是否符合已知条件
			{
				tmp.x=x;
				tmp.y=y;
				tmp.z=z;
				

				//判断a值是否已存在,如果存在,次数加1,否则添加到map中
				for(mIter=mManagerAgeAndCounts.begin(); mIter!=mManagerAgeAndCounts.end(); ++mIter)
				{
					if(mIter->first==a) 
					{
						++mIter->second;
					}
				}
				if(mIter==mManagerAgeAndCounts.end())
				{
					mManagerAgeAndCounts.insert(pair<int,int>(a,1));
				}

				//将这个可能的三个女孩的年龄组合添加到vecDaughterAge里
				vecDaughterAge.push_back(tmp);	
			}
		}
	}

	cout<<"根据已知条件得出可能的经理年龄和次数的组合:"<<endl;
	for(mIter=mManagerAgeAndCounts.begin(); mIter!=mManagerAgeAndCounts.end(); ++mIter)
	{
		cout<<mIter->first<<"  "<<mIter->second<<endl;
	}
	cout<<endl;
	cout<<"根据已知条件得出可能的三个女孩的年龄的组合:"<<endl;
	for(vIter=vecDaughterAge.begin(); vIter!=vecDaughterAge.end(); ++vIter)
	{
		cout<<vIter->x<<" "<<vIter->y<<" "<<vIter->z<<endl;
	}
	cout<<endl;
	
	int aReal;  //经理的真实年龄
	cout<<"根据追加判断的条件得出经理的年龄和三个女孩的年龄:"<<endl;
	for(mIter=mManagerAgeAndCounts.begin(); mIter!=mManagerAgeAndCounts.end(); ++mIter)
	{
		if(mIter->second !=1) //有追加条件,说明次数不可能为1
		{
			aReal=mIter->first;
			cout<<"经理的年龄是:"<<aReal<<endl;
			for(vIter=vecDaughterAge.begin(); vIter !=vecDaughterAge.end(); ++vIter)
			{
				a=(vIter->x)*(vIter->y)*(vIter->z);  //求出对应的a
				
				if(a==aReal && (vIter->x > vIter->y && vIter->y >= vIter->z))
				{
					cout<<"三个女孩的年龄分别为:"<<vIter->x<<" "<<vIter->y<<" "<<vIter->z<<endl;
				}
			}
		}
	}
	
	return 0;
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值