大疆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; }