Codeforces Round #424 (Div. 2) Problem D. Office Keys

时间:2022-12-30 10:06:53
 

题意 : 给你n个人,每个人有一个位置,给你k把钥匙,每个人拿到钥匙才能到办公室,每人一秒走一步么,问你所有人到办公室的最短时间。

题解 : 不难发现,当每个人拿的钥匙的位置确定了以后时间也确定了,我们就可以看每个人拿哪个钥匙,并且可以发现坐标靠前的人一定拿靠前的钥匙,否则结果不会更优。这样我们就可以先排序再dp。 dp[i,j] 表示 前 i 个人 在前j 把钥匙中拿到了全部的钥匙,转移方程为 dp[i,j] = max (dp[i - 1][j - 1],从第i个人到第j把钥匙再到办公室的距离)  (第i个人拿第j把钥匙的情况) dp [i,j] = min (dp[i][j],dp[i][j-1]); (j > i) 第 i 个人不拿第 j 把钥匙的情况。注意要开long long;

#include <iostream>
#include <algorithm>
#define ll long long
using namespacestd;
const int maxn =2005;
ll a[maxn] = {0};
ll b[maxn] = {0};
ll dp[maxn][maxn] = {0};
int n,k,p;
ll ab (ll x) {return x >0 ? x : -x;}
ll dist (ll x,ll y) {
    returnab(x - y) + ab(y -p);
}
int main () {
    ios_base ::sync_with_stdio(false);
    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 +n + 1);
    sort (b +1, b +k + 1);
    for (int i =1;i <= n;  ++ i) {
        for (int j =0;j <= k; ++ j)
            dp[i][j] =100000000009;
    }
    for (int i =1;i <= n; ++ i) {
        for (int j = i;j <=k; ++ j) {
            dp[i][j] =max (dp[i -1][j - 1],dist(a[i],b[j]));
            if (j > i)dp[i][j] = min (dp[i][j],dp[i][j - 1]);
        }
    }
    cout <<dp[n][k] <<endl;
    return0;
}