算法 Jack的完美点餐方案

Problem Description 
Jack最近喜欢到学校餐厅吃饭,好吃干净还便宜。 在学校餐厅,有a种汤,b种饭,c种面条,d种荤菜,e种素菜。 为了保证膳食搭配,Jack每顿饭都会点1~2样荤菜,1~2样素菜(不重复)。同时,在Jack心情好的时候,会点一样饭,再配上一种汤。在心情不好的时候,就只吃一种面条。 因为经济有限,Jack每次点餐的总价在min~max之间。Jack想知道,总共有多少种不同的点餐方案。 
Input 
输入数据第一行包含一个整数T,表示测试数据的组数,对于每组测试数据: 第一行为整数a,b,c,d,e(a,b,c,d,e>0 且 10>=a,b,c,d,e) 第二行为a个大于零的整数,表示a种汤的价格 第三行为b个大于零的整数,表示b种饭的价格 第四行为c个大于零的整数,表示c种面条的价格 第五行为d个大于零的整数,表示d种荤菜的价格 第六行为e个大于零的整数,表示e种素菜的价格 第七行为两个整数min max,表示每次点餐的价格范围 
Output 
对于每组测试数据,输出一行,包含一个整数,表示点餐方案数。 
Sample Input 
1 
2 2 2 2 2 
2 3
3 1 
5 2 
1 4 
3 6 
5 8 
Sample Output 
3 
用到了了以前自己写的快排
/*Sample code to read in test cases:*/
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;
template<class T>
int Partition(T A[],int p, int r)
{
	T x = A[r];
	int i = p-1;
	for(int j=p;j<=r-1;j++)
	{
		if(A[j]<= x)
		{
			++i;
			swap(A[i],A[j]);
		}
	}
	swap(A[r],A[i+1]);
	return i+1;
}

template<class T>
void QuickSort(T A[],int p, int r)
{
	if(p<r)
	{
		int q = Partition(A,p,r);
		QuickSort(A,p,q-1);
		QuickSort(A,q+1,r);
	}
}
void m_GetLine(fstream& file, istringstream& line)//将有效文件行读入字符流
{
	string lineBuffer;
	line.clear();
	while (!file.eof() && lineBuffer.length() == 0)
		getline(file, lineBuffer);
	line.str(lineBuffer);
}
void Initialization(fstream& file, int menu[],int p, int r)//菜单价格初始化
{
	istringstream line;
	m_GetLine(file, line);
	for (int i = p;i < r;++i)
		line >> menu[i];
}

int main()
{
	int a, b, c, d, e, n, cnt, min, max;
	fstream file;
	char sysInputFile[] = "{sysFileUrl}";
	file.open(sysInputFile);
	istringstream line;
	m_GetLine(file, line);
	line >> n;//数据组数
	while (n-- != 0)
	{
		m_GetLine(file, line);
		line >> a >> b >> c >> d >> e;
		int *Soup = new int[a];
		int *Rise = new int[b];
		int *Nuddle = new int[c];
		int *Meet = new int[d+1];
		int *Vegetable = new int[e+1];
		//初始化菜单价格,因为可能点到两份荤与两份素,添加价格为0的一种荤和一种素
		//每次选两份,这样当选到价格为0的荤或素时可视为只点了一份荤或素
		Meet[0] = 0;
		Vegetable[0] = 0;
		Initialization(file, Soup, 0, a);
		Initialization(file, Rise, 0, b);
		Initialization(file, Nuddle, 0, c);
		Initialization(file, Meet, 1, d+1);
		Initialization(file, Vegetable, 1, e+1);
		//为减少循环次数,对价格进行排序,当前使用快排
		QuickSort(Soup, 0, a-1);
		QuickSort(Rise, 0, b-1);
		QuickSort(Nuddle, 0, c-1);
		QuickSort(Meet, 0, d);
		QuickSort(Vegetable, 0, e);
		m_GetLine(file, line);
		line >> min >> max;
		cnt = 0;//解决方案数清0
		//使用回朔法(大概),通过price与max的判断去掉不必要的循环
		//例如,加上某样菜价后超过max,则由排序过的价格可知不必再进行后续判断
		for (int i = 1;i < d+1;++i)//荤
		{
			int price = Meet[i];
			if (price > max)//针对各种可能的菜单
				break;
			for (int j = 1;j < e+1; ++j)//素,为了增加剪枝效率,先嵌套一次素和荤
			{
				price += Vegetable[j];
				if (price > max)
				{
					price -= Vegetable[j];
					break;
				}
				for (int h = 0;h < i;++h)//第二种荤
				{
					price += Meet[h];
					if (price > max)
					{
						price -= Meet[h];
						break;
					}
					for (int k = 0;k < j;++k)//第二种素
					{
						price += Vegetable[k];
						if (price > max)
						{
							price -= Vegetable[k];
							break;
						}
						for (int m = 0;m < c;++m)//面条
						{
							price += Nuddle[m];
							if (price > max)
							{
								price -= Nuddle[m];
								break;
							}
							else if (price < min)
							{
								price -= Nuddle[m];
								continue;
							}
							else
							{
								price -= Nuddle[m];
								++cnt;
							}
						}
						for (int m = 0;m < b;++m)//米饭
						{
							price += Rise[m];
							if (price > max)
							{
								price -= Rise[m];
								break;
							}
							for (int x = 0;x < a;++x)//汤
							{
								price += Soup[x];
								if (price > max)
								{
									price -= Soup[x];
									break;
								}
								else if (price < min)
								{
									price -= Soup[x];
									continue;
								}
								else
								{
									price -= Soup[x];
									++cnt;
								}
							}
						}
					}
				}
			}
		}
			//do something
		cout << cnt << endl;
		delete []Soup;
		delete []Rise;
		delete []Nuddle;
		delete []Meet;
		delete []Vegetable;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值