题意 : 给你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; }