携程9.19笔试ak附解答
本来秋招已经结束了就不想做了,但闲着也是闲着,4道题做完感觉难度还是很友好的
一、计算网格内走k步获取的最大价值
先走第0列再走最后一行,再有多余的步数就在最后一个点和倒数第二个点循环走就行了
#include <iostream> using namespace std; typedef long long ll; int main(int argc, char const *argv[]) { /* code */ int q; cin >> q; while (q--) { ll n, m, k, res; cin >> n >> m >> k; if (k <= n - 1) { res = (1 + k) * k * m / 2; } else if (k <= n + m - 2) { ll a = n * (n - 1) * m / 2; k -= (n - 1); res = a + k * (n - 1) * m + (k + 1) * k / 2; } else { res = n * (n - 1) * m / 2 + (m - 1) * (n - 1) * m + m * (m - 1) / 2; k -= (n + m - 2); res += ((k / 2) * (2 * (n - 1) * m + 2 * m - 3)); if (k % 2) { res += ((n - 1) * m + m - 2); } } cout << res << endl; } return 0; }
二、选m个极差不超过k的数消掉最小的数,求剩余最少的数字数量
排序从小到大遍历看最小的数能不能被消掉就行
#include <iostream> #include <algorithm> using namespace std; const int maxn = 1e6 + 100; int a[maxn]; int n, m, k; int main(int argc, char const *argv[]) { /* code */ cin >> n >> m >> k; for (int i = 1; i <= n; i++) { cin >> a[i]; } int total = n; sort(a + 1, a + 1 + n); for (int i = 1; i <= n; i++) { int nxt = i + m - 1; if (nxt > n) { break; } if (a[nxt] - a[i] <= k) { total--; } } cout << total << endl; return 0; }
三、选k个长度不超过l的区间改变数字,求最后剩余的最小数字
二分最小数字即可
#include <algorithm> #include <iostream> #include <queue> #include <utility> using namespace std; const int maxn = 1e5 + 100; int a[maxn]; int b[maxn]; int n, k, l; bool check(int val) { int last = 0; int cnt = 0; for (int i = 1; i <= n; i++) { if (a[i] < val) { if (last == 0) { last = i; cnt++; } else if (i - last + 1 > l) { last = i; cnt++; } } } return cnt <= k; } int main(int argc, const char **argv) { cin >> n >> k >> l; for (int i = 1; i <= n; i++) { cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + 1 + n); int lef = 1, rig = n; int result = -1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (check(b[mid])) { result = mid; lef = mid + 1; } else { rig = mid - 1; } } cout << b[result] << endl; return 0; }
四、求所有员工拿到通行证再到公司的最短时间
首先把通行证和员工的坐标排序,可以确定的是如果最优解中第i个员工拿了第j个通行证,那么前i-1个员工的通行证一定在前j-1个里选,这样可以用动态规划求解
#include <iostream> #include <algorithm> #include <cmath> using namespace std; int n, k, p; int a[2010]; int b[2010]; int dp[2010][2010]; int main(int argc, char const *argv[]) { /* code */ cin >> n >> k >> p; for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = 1; i <= k; i++) { cin >> b[i]; } sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + k); for (int i = 1; i <= n; i++) { dp[i][0] = INT32_MAX; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= k; j++) { if (j < i) { dp[i][j] = INT32_MAX; } else { dp[i][j] = max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j])); dp[i][j] = min(dp[i][j], dp[i][j - 1]); } } } int res = INT32_MAX; for (int i = n; i <= k; i++) { res = min(res, dp[n][i]); } cout << res << endl; return 0; }