首页 > 代码库 > 猪的安家

猪的安家

题目描述:

Andy和Mary养了很多猪。他们想要给猪安家。但是Andy没有足够的猪圈,很多猪只能够在一个猪圈安家。举个例子,假如有16头猪,Andy建了3个猪圈,为了保证公平,剩下1头猪就没有地方安家了。Mary生气了,骂Andy没有脑子,并让他重新建立猪圈。这回Andy建造了5个猪圈,但是仍然有1头猪没有地方去,然后Andy又建造了7个猪圈,但是还有2头没有地方去。Andy都快疯了。你对这个事情感兴趣起来,你想通过Andy建造猪圈的过程,知道Andy家至少养了多少头猪。  输入  

输入包含多组测试数据。每组数据第一行包含一个整数n (n <= 10) – Andy建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示Andy建立了ai个猪圈,有bi头猪没有去处。你可以假定(ai, aj) = 1.  输出  

输出包含一个正整数,即为Andy家至少养猪的数目。 

样例输入  

3 1 

5 1 

7 2  

样例输出  

16

 

题目分析:

设有c满足所有等式c = ai*x + bi则要选取出最小的c,其中x是一个整数。

 

解题思路:

当然有很多的解法,比如矩阵解方程或者c从1开始穷举出第一个满足所有等式的c。我们可以考虑第二种方法,但是没必要从1开始穷举,从max{ai}开始,设max{ai}的情况下,一个猪圈里养x=0只猪开始,然后得出c后,用c依次校验前面的所有式子,如果得出其他式子的x也都是一个整数,则满足,否则max{ai}的x+1,继续按照上述规则循环校验。


#include <algorithm>

//线性等式ax+b=y
//这里xy都为离散变量
class LinearEquation
{
private:
	int a;
	int b;
public:
	LinearEquation() :a(0), b(0){}
	LinearEquation(int a, int b) :a(a), b(b){}
	int GetY(int x)const
	{
		return a*x + b;
	}
	bool IsRightY(int y)const
	{//是否是正确的y,在x不为整数时认为y不正确
		return ((y - b) % a) == 0;
	}
	bool operator > (const LinearEquation &f) const
	{
		return a > f.a;
	}
};


int GetPigNumber(int eNumber,LinearEquation *arr)
{//eNumber为给出的等式的数量,arr为存储给出等式的集合
	std::sort(arr, arr + eNumber, [](const LinearEquation &l1, const LinearEquation &l2){return l1 > l2; });//按线性等式中的a的大小来排序
	int perPigpenNumber = 0;//每个猪圈养的猪的数量
	int pigNumber = 0;//猪的数量
	while (1)
	{//循环开始寻找多少只猪能满足所有等式
		bool isARightY = true;//假设是正确的y
		pigNumber = arr[0].GetY(perPigpenNumber++);
		std::for_each(arr, arr + eNumber, [&](const LinearEquation &f){
			if (!f.IsRightY(pigNumber))
			{//如果有一个等式不满足条件
				isARightY = false;
				return;
			}
		});
		if (isARightY)//所有Y得出的X都是整数
			return pigNumber;
	}
}

void InputBuildingPigpen()
{
	int num = 0;
	if (scanf_s("%d", &num) == EOF || !num)//如果输入的num为0就退出
		return;
	LinearEquation *pigPen = new LinearEquation[num];
	for (int i = 0; i < num; ++i)
	{
		int a = 0, b = 0;
		scanf_s("%d%d", &a, &b);
		pigPen[i] = LinearEquation(a,b);
	}
	printf("猪的数量为:%d\n", GetPigNumber(num, pigPen));
	delete[] pigPen;
}

int _tmain(int argc, _TCHAR* argv[])
{
	InputBuildingPigpen();
	return 0;
}


本代码有个问题就是没有对输入数据做错误校验,其实做错误校验也不难,只需要校验给出的两个等式会不会出现矛盾就行了,矛盾的条件是aj是ai的倍数,但是bj和bi不相等。

猪的安家