【c++】大疆笔试题,应该怎么吃呢

题目如下:

时间限制:CC++语言1000Ms;其他语言3000 Ms
内存限制:CC+语言65536KB;其他语言589824KB
题目描述:
小w非常喜欢吃零食,经常都会去零食间里购买半价的零食吃,但是他为了控制自己的体重,因此会限制自己买零食的开销在某个数值以内。
但是小W有一个特别的爱好,他对于某些零食特别的喜欢,并且会对这些零食的喜爱程度进行排序。对于零食A和零食B,如果小W对零食A的喜爱程度大于对零食B的喜爱程度,那么每次拿零食的时候,一定会确保A的数目比B多。
现在零食间里有N种零食,假设每种零食都是取不完的,但小W每次都会刚好花完所有的开销,那么小W去取零食的时候应该有多少种可能的取法呢?
输入
输入包含多组测试数据,每组数组:
第一行:买零食的开销V(V<1000和所有的零食种类数目N(N<200
第二行:第i个正整数表示第i种零食的价格ci(ci<1000
第三行:特别喜欢的零食的种类数M(2<=M<=N
第四行:按照对M种零食的喜爱程度从高到低排序,第i种零食的喜爱程度会大于第计+1种,保证不会形成环
输出
对于每组测试数据
输出一个整数as,表示在满足小W的特殊偏好的情况下,并且花光所有开销,有多少可能方案。由于ansi可能很大,因此最终结果ansi%100000

下面是暴力穷举法的代码,笔者才浅,没想到特别好的算法来解决这个问题,如果有更好的算法,希望能在评论区指出,多谢!

#include 
#include 

using namespace std;

int result_num = 0;

//打印vector
template <typename T>
void print_vector(vector<T> vec) {
	cout << '[';
	//遍历输出,空格间隔
	for (auto i = vec.begin(); i != vec.end(); i++) {
		if (i + 1 == vec.end())
			cout << *i << ']' << endl;
		else
			cout << *i << " ";
	}
}

//计算方案result所需花销
int cal_cost(const vector<int>& results, const vector<int>& costs) {
	int cost = 0;
	for (size_t i = 0; i < results.size(); i++)
	{
		cost += results[i] * costs[i];
	}
	return cost;
}

//判断方案results花销够不够
bool cost_enough(int all_cost, const vector<int>& results, const vector<int>& costs) {
	return all_cost >= cal_cost(results, costs);
}

//判断方案是否可行
bool good_result(int all_cost, const vector<int>& results, const vector<int>& costs) {
	return all_cost == cal_cost(results, costs);
}

//判断喜爱程度是否满足要求
bool good_favor(const vector<int>& results, const vector<int>& favors) {
	//遍历favors
	for (int i = 0; i < favors.size() - 1; i++) {
		//如果后一个零食个数不为0
		if (results[favors[i + 1]] != 0) {
			if (results[favors[i]] <= results[favors[i + 1]])
				return false;
		}
	}
	return true;
}

//暴力穷举,
void solve(int all_cost, int ope_index, const vector<int>& costs, const vector<int>& favors, vector<int>& results) {
	//只要花销够,就继续循环
	while (cost_enough(all_cost, results, costs)) {
		//如果花销刚好花完
		if (good_result(all_cost, results, costs)) {
			//如果满足喜爱程度要求,则解+1
			if (good_favor(results, favors)) {
				result_num++; 
				print_vector<int>(results);
			}
			//返回上级
			results[ope_index] = 0;
			return;
		}
		//不拿当前零食
		//如果不是最后一个零食,处理下一个零食
		if (ope_index + 1 < costs.size())
			solve(all_cost, ope_index + 1, costs, favors, results);
		else
		{
			//剩余开销
			int left_cost = all_cost - cal_cost(results, costs);
			//如果刚好用完,且满足要求,解+1
			if (left_cost%costs[ope_index] == 0 && good_favor(results, favors)) {
				results[ope_index] = left_cost / costs[ope_index];
				result_num++;
				print_vector<int>(results);
			}
			//返回上级
			results[ope_index] = 0;
			return;
		}
		//拿当前零食,继续循环
		results[ope_index]++;
	}
	//如果花销不够,当前拿取数清零,返回上级
	results[ope_index] = 0;
	return;
}

int main()
{
	//输入
	int case_num;//案例数
	cin >> case_num;
	for (int c = 0; c < case_num; c++) {

		int all_cost, snack_num;//总开销,零食种类数
		int favor_num;//喜爱零食的数量
		vector<int> costs;//开销列表
		vector<int> favors;//喜爱程度列表,越靠前越喜

		cin >> all_cost >> snack_num;
		for (int i = 0; i < snack_num; i++) {
			int cost;
			cin >> cost;
			costs.push_back(cost);
		}
		cin >> favor_num;
		for (int i = 0; i < favor_num; i++) {
			int snack;
			cin >> snack;
			favors.push_back(snack);
		}
		//暴力穷举
		vector<int> results;
		for (size_t i = 0; i < costs.size(); i++)
		{
			results.push_back(0);
		}
		solve(all_cost, 0, costs, favors, results);
		//打印结果
		cout << "result number:" << result_num % 100000 << endl;
		//结果清零
		result_num = 0;
	}
	
}
/*
input:
2
10 3
4 5 6
2
0 1
20 5
2 4 5 6 7
2
1 2
*/


运行结果

【c++】大疆笔试题,应该怎么吃呢_第1张图片

你可能感兴趣的:(c++回顾)