得物笔试题目(2023-08-23)
1. 开幕式排练
这道题目想明白了挺简单的,其实就是排序,排序完以后我们希望将相近的数字摆到一起,怎么算相近?两个挨着算相近,但是这样首尾差别是最大的,而题目给出的是最大的身高差,这样操作没有意义。
既然需要处理首尾地方,我们首先排序,奇数位置的数字为一组,偶数位置的数字为一组,将这两组首尾相连,一定是最小的身高差。因为,出了连接处,所有的数字都只差了2个位次,首尾处差了1个位次。
无法找到比这个解更优的排队方案了,因此,它就是正确的。
代码如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> vec(n);
for (int i = 0; i < n; i++) {
cin >> vec[i];
}
sort(vec.begin(), vec.end());
int maxVal = 0;
for (int i = 0; i < n; i++) {
if (i - 2 >= 0) {
maxVal = max(maxVal, vec[i] - vec[i - 2]);
}
}
maxVal = max(maxVal, (vec[1] - vec[0]));
maxVal = max(maxVal, vec[vec.size() - 1] - vec[vec.size() - 2]);
cout << maxVal;
return 0;
}
2. 最少数字
背包问题,能过100%:
#include<vector>
#include<iostream>
using namespace std;
int main() {
int N, M;
cin >> N >> M;
vector<int> vec(N);
for (int i = 0; i < N; i++) {
cin >> vec[i];
}
vector<int> dp(M + 1);
dp[0] = 0;
for (int i = 1; i <= M; i++) {
dp[i] = 0x3f3f3f3f;
}
for (int i = 0; i < N; i++) {
for (int j = M; j >= 0; j--) {
if (j - vec[i] >= 0)
dp[j] = min(dp[j], dp[j - vec[i]] + 1);
}
if(dp[M] == 1) break;
}
if (dp[M] == 0x3f3f3f3f)
cout << "No solution";
else
cout << dp[M];
return 0;
}
最开始没看出来,采用dfs,只能过45%:
#include<iostream>
#include<vector>
using namespace std;
void dfs(int& minNum, int curNum, int curSum, int M, vector<int>& vec, int index) {
if (curSum == M) {
if (curNum < minNum) {
minNum = curNum;
}
return;
}
if (curSum > M) { // 后边不可能存在解了
return;
}
if (index >= vec.size())return;
// 要 index 位的数字
dfs(minNum, curNum + 1, curSum + vec[index], M, vec, index + 1);
// 不要 index 的数字
dfs(minNum, curNum, curSum, M, vec, index + 1);
return;
}
int main() {
int N, M;
cin >> N >> M;
vector<int> vec(N);
for (int i = 0; i < N; i++) {
cin >> vec[i];
}
int minVal = 0x3f3f3f3f;
dfs(minVal, 0, 0, M, vec, 0);
cout << minVal;
return 0;
}
排序优化了下,能过63%:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int dfs(int curNum, int curSum, int M, vector<int>& vec, int index) {
if (curSum == M) {
return curNum;
}
if (curSum > M) { // 后边不可能存在解了
return -1;
}
if (index >= vec.size())return -1;
int res;
// 要 index 位的数字
res = dfs(curNum + 1, curSum + vec[index], M, vec, index + 1);
if (res != -1) {
return res;
}
// 不要 index 的数字
res = dfs(curNum, curSum, M, vec, index + 1);
if (res != -1) {
return res;
}
return -1;
}
int main() {
int N, M;
cin >> N >> M;
vector<int> vec(N);
for (int i = 0; i < N; i++) {
cin >> vec[i];
}
sort(vec.begin(), vec.end(), greater<int>());
// int minVal = 0x3f3f3f3f;
int minVal = dfs(0, 0, M, vec, 0);
if (minVal == -1)
cout << "No solution";
else
cout << minVal;
return 0;
}

查看3道真题和解析