大疆2019.8.6 软件笔试第三题技术分享 应该怎么吃



输入包含都租测试数据,每组数组:
第一行:买零食的开销V(V<1000)和所有零食种类数目N(N<200)
第二行:第i个正整数表示第i种零食的价格c_i(c_i<1000)
第三行:特别喜欢的零食的种类数M(2<=M<=N)
第四行:按照对M种零食的喜爱程度从高到低排序,第i种零食的喜爱程度会大于第i+1,保证不会形成环

对于每组测试数据:
输出一个整数ans,表示在满足小W的特殊爱好的情况下,并且花光所有开销,有多少可能方案;
此题涉及背包问题的求方案总数问题,使用贪心算法,不能AC,最后思考出的含条件的动态规划,使用自测数据已经通过,大致
方法是:
1.按照零食的喜爱程度重新排序,如零食价格为1 2 5 8,喜爱列表为2 3,则排序后的价格表为2 5 1 8,最后根据更新
后的价格列表进行下一步操作
2.动态规划状态转移的时候将零食依赖程度的隐含条件(价格列表前面的数量大于列表靠后的数量)附在状态转移中
//*******************大疆第三题*************************
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

int w[1001];
vector<int> v(1001);
int v1[1001] = {0};
struct F
{
	int value;
	int num;
}f[1001];

int main()
{
	int m, n;
	int dep_num;
	while (cin >> m >> n)
	{
		for (int i = 1; i <= n; i++)
			cin >> v[i];
		cin >> dep_num;
		vector<int> dep(dep_num+1);
		vector<int> dep_list(dep_num + 1);
		for (int i = 1; i <= dep_num; i++)
			cin >> dep[i];
		for (int i = 1; i < dep.size(); i++)
			dep_list[i] = v[dep[i]];
		f[0].value = 1;
		for (int i = 1; i < 1000; i++)
		{
			f[i].value = 0;
			f[i].num = 0;
		}
		int flag = 1;
		for (int i = 1; i <= dep.size() - 1; i++)
		{
			v1[flag++] = v[dep[i]];
		}
		for (int i = 1; i <= dep.size() - 1; i++)
		{
			int tmp = dep_list[i];
			vector<int>::iterator it = find(v.begin(), v.begin() + n, tmp);
			if (it != v.end())
			{
				v.erase(it);
			}
		}
		for (int i = flag; i <= n; i++)
		{
			v1[i] = v[i-flag+1];
		}
		f[0].value = 1;
		for (int i = 1; i <= n; i++)
		{
			for (int j = m; j >= v1[i]; j--)
			{
				for (int k = 1; k <=j / v1[i]; k++)
				{
					if (i == 1 && f[j - k*v1[i]].value == 1)
					{
						f[j].value += f[j - k*v1[i]].value;
						f[j].num = k;
					}
					else if (i>1&&i<dep.size()&&f[j-k*v1[i]].value>=1)
					{
						if (k >= f[j - k*v1[i]].num)
							continue;
						else
						{
							f[j].value += f[j - k*v1[i]].value;
							f[j].num = k;
						}
					}
					else
					{
						f[j].value += f[j - k*v1[i]].value;
					}
											
				}
			}
		}
		cout << f[m].value << endl;
	}
	
	system("pause");
	return 0;
}


#uc##大疆##笔试题目##C++工程师#
全部评论
按喜好程度排序, 每次按取的件数和当前花费金额分类记录, 剩下普通零食按完全背包更新就可以了, 这是后来改的, 不一定完全正确, 欢迎讨论..觉得不错的点个赞呗 #include<bits/stdc++.h> using namespace std; vector<int> f; bool cmp(const int& a, const int& b) { return f[a] < f[b]; } int main(){ int m, n, v, t; while (cin >> v >> n) { vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } cin >> m; f = vector<int>(n, n); for (int i = 0; i < m; i++) { cin >> t; f[t - 1] = i; } sort(a.begin(), a.end(), cmp); vector<vector<int> > dp(v / a[0] + 1, vector<int>(v + 1, 0)); int res = 0; // 先挑选最喜欢的零食, 无约束 for (int i = 0; i < v / a[0] + 1; i++) { dp[i][i * a[0]] = 1; } // 按喜欢程度依次挑选其他特别喜欢的零食, for(int i = 1; i < m; i++) { vector<vector<int>> t = move(dp); int size = v / a[i] + 1; dp = vector<vector<int> >(size, vector<int>(v + 1, 0)); for (int j = 1; j < t.size(); j++) { // 每次取的要比前一种要少 for (int k = min(size - 1, j - 1); k >= 0; k--) { for (int l = k * a[i]; l <= v; l++){ dp[k][l] = (dp[k][l] + t[j][l - k * a[i]]) % 10000007; } } } } // 统计各花费的方案数 vector<int> cur(v + 1, 0); for (int i = 0; i <= v; i++) { for (int j = 0; j < dp.size(); j++) { cur[i] = (cur[i] + dp[j][i]) % 10000007; } } // 按完全背包更新其余零食 for (int i = m; i < n; i++) { for (int j = a[i]; j <= v; j++) { cur[j] = (cur[j] + cur[j - a[i]]) % 10000007; } } cout << cur[v] << endl; } return 0; }
点赞 回复 分享
发布于 2019-08-09 14:14
果然讨论有助于发现问题, 上面开始的排序写错了 重新改了如下 #include<bits/stdc++.h> using namespace std; int main(){ int m, n, v, t; while (cin >> v >> n) { vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } cin >> m; vector<int> f(n); for (int i = 0; i < m; i++) { cin >> t; f[i] = a[t - 1]; a[t - 1] = -1; } for (int i = 0, j = m; j < n; i++) { if (a[i] > 0) { f[j++] = a[i]; } } a = move(f); vector<vector<int> > dp(v / a[0] + 1, vector<int>(v + 1, 0)); int res = 0; // 先挑选最喜欢的零食, 无约束 for (int i = 0; i < v / a[0] + 1; i++) { dp[i][i * a[0]] = 1; } // 按喜欢程度依次挑选其他特别喜欢的零食, for(int i = 1; i < m; i++) { vector<vector<int>> t = move(dp); int size = v / a[i] + 1; dp = vector<vector<int> >(size, vector<int>(v + 1, 0)); for (int j = 1; j < t.size(); j++) { // 每次取的要比前一种要少 for (int k = min(size - 1, j - 1); k >= 0; k--) { for (int l = k * a[i]; l <= v; l++){ dp[k][l] = (dp[k][l] + t[j][l - k * a[i]]) % 10000007; } } } } // 统计各花费的方案数 vector<int> cur(v + 1, 0); for (int i = 0; i <= v; i++) { for (int j = 0; j < dp.size(); j++) { cur[i] = (cur[i] + dp[j][i]) % 10000007; } } // 按完全背包更新其余零食 for (int i = m; i < n; i++) { for (int j = a[i]; j <= v; j++) { cur[j] = (cur[j] + cur[j - a[i]]) % 10000007; } } cout << cur[v] << endl; } return 0; }
点赞 回复 分享
发布于 2019-08-09 16:29

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
双非一本失业第二年:《机器视觉垃圾分类》
点赞 评论 收藏
分享
评论
点赞
8
分享
牛客网
牛客企业服务