cf831D(dp)

题目链接: 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
", sol);
31     return 0;
32 }
View Code
原文地址:https://www.cnblogs.com/geloutingyu/p/7181935.html