题目链接: http://codeforces.com/contest/831/problem/D
题意: 有 n 个人和 k 把钥匙, 数组 a 为 n 个人的初始位置, 数组 b 为 k 把钥匙的初始位置, n 个人都要先拿到一把钥匙然后在到 p 位置去, 问所有人都到 p 位置所需要的最少时间是多少.
思路: 这题即可以 dp 也可以直接二分答案.
dp 思路为: dp[i][j]存储前i个人在前j把钥匙中每个人得到钥匙的最小花费.
那么动态转移方程式为:
if(i == j) dp[i][j] = max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j]))
else if(j > i) dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(a[i] - b[j]) + abs(p - b[j])))
代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <stdio.h> 4 using namespace std; 5 6 const int MAXN = 1e3 + 10; 7 int a[MAXN], b[MAXN << 1], dp[MAXN][MAXN << 1];//dp[i][j]存储前i个人在前j把钥匙中每个人得到钥匙的最小花费 8 9 int main(void){ 10 int n, k, p; 11 scanf("%d%d%d", &n, &k, &p); 12 for(int i = 1; i <= n; i++){ 13 scanf("%d", &a[i]); 14 } 15 for(int i = 1; i <= k; i++){ 16 scanf("%d", &b[i]); 17 } 18 sort(a + 1, a + n + 1); 19 sort(b + 1, b + k + 1); 20 for(int i = 1; i <= n; i++){ 21 for(int j = i; j <= k; j++){ 22 if(i == j) dp[i][j] = max(dp[i - 1][j - 1], abs(b[j] - a[i]) + abs(p - b[j])); 23 else dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], abs(b[j] - a[i]) + abs(p - b[j]))); 24 } 25 } 26 int sol = 2e9 + 10; 27 for(int i = n; i <= k; i++){ 28 sol = min(sol, dp[n][i]); 29 } 30 printf("%d\n", sol); 31 return 0; 32 }